Task: Sokoban




Go: package main

import (
    "fmt"
    "strings"
)

func main() {
    level := `
#######
#     #
#     #
#. #  #
#. $$ #
#.$$  #
#.#  @#
#######`
    fmt.Printf("level:%s\n", level)
    fmt.Printf("solution:\n%s\n", solve(level))
}   
    
func solve(board string) string {
    buffer = make([]byte, len(board))
    width := strings.Index(board[1:], "\n") + 1
    dirs := []struct {
        move, push string 
        dPos       int
    }{
        {"u", "U", -width},
        {"r", "R", 1},
        {"d", "D", width},
        {"l", "L", -1},
    }
    visited := map[string]bool{board: true}
    open := []state{state{board, "", strings.Index(board, "@")}}
    for len(open) > 0 {
        s1 := &open[0]
        open = open[1:]
        for _, dir := range dirs {
            var newBoard, newSol string
            newPos := s1.pos + dir.dPos
            switch s1.board[newPos] {
            case '$', '*':
                newBoard = s1.push(dir.dPos)
                if newBoard == "" || visited[newBoard] {
                    continue
                }
                newSol = s1.cSol + dir.push
                if strings.IndexAny(newBoard, ".+") < 0 {
                    return newSol
                }
            case ' ', '.':
                newBoard = s1.move(dir.dPos)
                if visited[newBoard] {
                    continue
                }
                newSol = s1.cSol + dir.move
            default:
                continue
            }
            open = append(open, state{newBoard, newSol, newPos})
            visited[newBoard] = true
        }
    }
    return "No solution"
}

type state struct {
    board string
    cSol  string
    pos   int
}

var buffer []byte

func (s *state) move(dPos int) string {
    copy(buffer, s.board)
    if buffer[s.pos] == '@' {
        buffer[s.pos] = ' '
    } else {
        buffer[s.pos] = '.'
    }
    newPos := s.pos + dPos
    if buffer[newPos] == ' ' {
        buffer[newPos] = '@'
    } else {
        buffer[newPos] = '+'
    }
    return string(buffer)
}

func (s *state) push(dPos int) string {
    newPos := s.pos + dPos
    boxPos := newPos + dPos
    switch s.board[boxPos] {
    case ' ', '.':
    default:
        return ""
    }
    copy(buffer, s.board)
    if buffer[s.pos] == '@' {
        buffer[s.pos] = ' '
    } else {
        buffer[s.pos] = '.'
    }
    if buffer[newPos] == '$' {
        buffer[newPos] = '@'
    } else {
        buffer[newPos] = '+'
    }
    if buffer[boxPos] == ' ' {
        buffer[boxPos] = '$'
    } else {
        buffer[boxPos] = '*'
    }
    return string(buffer)
}




Python: from array import array
from collections import deque
import psyco

data = []
nrows = 0
px = py = 0
sdata = ""
ddata = ""

def init(board):
    global data, nrows, sdata, ddata, px, py
    data = filter(None, board.splitlines())
    nrows = max(len(r) for r in data)

    maps = {' ':' ', '.': '.', '@':' ', '
    mapd = {' ':' ', '.': ' ', '@':'@', '

    for r, row in enumerate(data):
        for c, ch in enumerate(row):
            sdata += maps[ch]
            ddata += mapd[ch]
            if ch == '@':
                px = c
                py = r

def push(x, y, dx, dy, data):
    if sdata[(y+2*dy) * nrows + x+2*dx] == '
       data[(y+2*dy) * nrows + x+2*dx] != ' ':
        return None

    data2 = array("c", data)
    data2[y * nrows + x] = ' '
    data2[(y+dy) * nrows + x+dx] = '@'
    data2[(y+2*dy) * nrows + x+2*dx] = '*'
    return data2.tostring()

def is_solved(data):
    for i in xrange(len(data)):
        if (sdata[i] == '.') != (data[i] == '*'):
            return False
    return True

def solve():
    open = deque([(ddata, "", px, py)])
    visited = set([ddata])
    dirs = ((0, -1, 'u', 'U'), ( 1, 0, 'r', 'R'),
            (0,  1, 'd', 'D'), (-1, 0, 'l', 'L'))

    lnrows = nrows
    while open:
        cur, csol, x, y = open.popleft()

        for di in dirs:
            temp = cur
            dx, dy = di[0], di[1]

            if temp[(y+dy) * lnrows + x+dx] == '*':
                temp = push(x, y, dx, dy, temp)
                if temp and temp not in visited:
                    if is_solved(temp):
                        return csol + di[3]
                    open.append((temp, csol + di[3], x+dx, y+dy))
                    visited.add(temp)
            else:
                if sdata[(y+dy) * lnrows + x+dx] == '
                   temp[(y+dy) * lnrows + x+dx] != ' ':
                    continue

                data2 = array("c", temp)
                data2[y * lnrows + x] = ' '
                data2[(y+dy) * lnrows + x+dx] = '@'
                temp = data2.tostring()

                if temp not in visited:
                    if is_solved(temp):
                        return csol + di[2]
                    open.append((temp, csol + di[2], x+dx, y+dy))
                    visited.add(temp)

    return "No solution"


level = """\









psyco.full()
init(level)
print level, "\n\n", solve()