### constant

MAX_INT = (1 << 30)
DXYS = [[1, 0], [0, -1], [-1, 0], [0, 1]]

### main

while true
  $w, $h = gets.strip.split(' ').map{|s| s.to_i}
  break if $w == 0 && $h == 0

  start = nil
  goal = nil

  brds = $h.times.map{[]}

  for y in (0...$h)
    hl = gets.strip
    for x in (0...$w)
      case hl[x]
      when '.'
        brds[y][x] = -1
      when '#'
        brds[y][x] = nil
      when 'X'
        brds[y][x] = 'X'
      when 'S'
        start = [x, y]
        brds[y][x] = -1
      when 'G'
        goal = [x, y]
        brds[y][x] = -1
      end
    end
  end

  nice = 0
  ices = []

  for y in (0...$h)
    for x in (0...$w)
      if brds[y][x] == 'X'
        ices[nice] = 1
        brds[y][x] = nice
        q = [[x, y]]

        while ! q.empty?
          x0, y0 = q.shift

          for dxy in DXYS
            x1 = x0 + dxy[0]
            y1 = y0 + dxy[1]
            if x1 >= 0 && x1 < $w && y1 >= 0 && y1 < $h && brds[y1][x1] == 'X'
              ices[nice] += 1
              brds[y1][x1] = nice
              q << [x1, y1]
            end
          end
        end

        nice += 1
      end
    end
  end

  ices.map!{|k| k / 2 }

  #p brds
  #p ices

  dists = $h.times.map{$w.times.map{Hash.new(MAX_INT)}}
  dists[start[1]][start[0]][ices] = 0
  q = [start + [ices]]

  while ! q.empty?
    #p q

    xy = q.min{|a, b| dists[a[1]][a[0]][a[2]] <=> dists[b[1]][b[0]][b[2]]}
    q.delete xy

    break if xy == goal

    x, y, ics = xy

    for dxy in DXYS
      x0 = x + dxy[0]
      y0 = y + dxy[1]

      if x0 >= 0 && x0 < $w && y0 >= 0 && y0 < $h
        ic = brds[y0][x0]
        next if ic.nil?

        if ic >= 0
          next if ics[ic] <= 0
          ics0 = ics.clone
          ics0[ic] -= 1
        else
          ics0 = ics
        end

        d0 = dists[y][x][ics] + 1
        if dists[y0][x0][ics0] > d0
          dists[y0][x0][ics0] = d0
          q << [x0, y0, ics0]
        end
      end
    end
  end
  #p dists

  gx, gy = goal
  puts dists[gy][gx].values.min
end