Task: Maze solving




Go: package main

import (
    "bytes"
    "fmt" 
    "math/rand"
    "time"
)

type maze struct { 
    c2 [][]byte 
    h2 [][]byte 
    v2 [][]byte 
}

func newMaze(rows, cols int) *maze {
    c := make([]byte, rows*cols)              
    h := bytes.Repeat([]byte{'-'}, rows*cols) 
    v := bytes.Repeat([]byte{'|'}, rows*cols) 
    c2 := make([][]byte, rows)                
    h2 := make([][]byte, rows)                
    v2 := make([][]byte, rows)                
    for i := range h2 {
        c2[i] = c[i*cols : (i+1)*cols]
        h2[i] = h[i*cols : (i+1)*cols]
        v2[i] = v[i*cols : (i+1)*cols]
    }
    return &maze{c2, h2, v2}
}   
    
func (m *maze) String() string {
    hWall := []byte("+---")
    hOpen := []byte("+   ")
    vWall := []byte("|   ")
    vOpen := []byte("    ")
    rightCorner := []byte("+\n")
    rightWall := []byte("|\n")
    var b []byte
    for r, hw := range m.h2 {
        for _, h := range hw {
            if h == '-' || r == 0 {
                b = append(b, hWall...)
            } else {
                b = append(b, hOpen...)
                if h != '-' && h != 0 {
                    b[len(b)-2] = h
                }
            }
        }
        b = append(b, rightCorner...)
        for c, vw := range m.v2[r] {
            if vw == '|' || c == 0 {
                b = append(b, vWall...)
            } else {
                b = append(b, vOpen...)
                if vw != '|' && vw != 0 {
                    b[len(b)-4] = vw
                }
            }
            if m.c2[r][c] != 0 {
                b[len(b)-2] = m.c2[r][c]
            }
        }
        b = append(b, rightWall...)
    }
    for _ = range m.h2[0] {
        b = append(b, hWall...)
    }
    b = append(b, rightCorner...)
    return string(b)
}

func (m *maze) gen() {
    m.g2(rand.Intn(len(m.c2)), rand.Intn(len(m.c2[0])))
}

const (
    up = iota
    dn
    rt
    lf
)

func (m *maze) g2(r, c int) {
    m.c2[r][c] = ' '
    for _, dir := range rand.Perm(4) {
        switch dir {
        case up:
            if r > 0 && m.c2[r-1][c] == 0 {
                m.h2[r][c] = 0
                m.g2(r-1, c)
            }
        case lf:
            if c > 0 && m.c2[r][c-1] == 0 {
                m.v2[r][c] = 0
                m.g2(r, c-1)
            }
        case dn:
            if r < len(m.c2)-1 && m.c2[r+1][c] == 0 {
                m.h2[r+1][c] = 0
                m.g2(r+1, c)
            }
        case rt:
            if c < len(m.c2[0])-1 && m.c2[r][c+1] == 0 {
                m.v2[r][c+1] = 0
                m.g2(r, c+1)
            } 
        }
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    const height = 4
    const width = 7
    m := newMaze(height, width)
    m.gen() 
    m.solve(
        rand.Intn(height), rand.Intn(width),
        rand.Intn(height), rand.Intn(width))
    fmt.Print(m)
}   
    
func (m *maze) solve(ra, ca, rz, cz int) {
    var rSolve func(ra, ca, dir int) bool
    rSolve = func(r, c, dir int) bool {
        if r == rz && c == cz {
            m.c2[r][c] = 'F'
            return true
        }
        if dir != dn && m.h2[r][c] == 0 {
            if rSolve(r-1, c, up) {
                m.c2[r][c] = '^'
                m.h2[r][c] = '^'
                return true
            }
        }
        if dir != up && r+1 < len(m.h2) && m.h2[r+1][c] == 0 {
            if rSolve(r+1, c, dn) {
                m.c2[r][c] = 'v'
                m.h2[r+1][c] = 'v'
                return true
            }
        }
        if dir != lf && c+1 < len(m.v2[0]) && m.v2[r][c+1] == 0 {
            if rSolve(r, c+1, rt) {
                m.c2[r][c] = '>'
                m.v2[r][c+1] = '>'
                return true
            }
        }
        if dir != rt && m.v2[r][c] == 0 {
            if rSolve(r, c-1, lf) {
                m.c2[r][c] = '<'
                m.v2[r][c] = '<'
                return true
            }
        }
        return false
    }
    rSolve(ra, ca, -1)
    m.c2[ra][ca] = 'S'
}








Ada: with Ada.Text_IO;

procedure Maze_Solver is

   X_Size: constant Natural := 45;
   Y_Size: constant Natural := 17;

   subtype X_Range is Natural range 1 .. X_Size;
   subtype Y_Range is Natural range 1 .. Y_Size;

   East:  constant X_Range := 2;
   South: constant Y_Range := 1;

   X_Start: constant X_Range  := 3; 
   Y_Start: constant Y_Range  := 1;
   X_Finish: constant X_Range := X_Size-East; 
   Y_Finish: constant Y_Range := Y_Size; 

   type Maze_Type is array (Y_Range) of String(X_Range);

   function Solved(X: X_Range; Y: Y_Range) return Boolean is
   begin
      return (X = X_Finish) and (Y = Y_Finish);
   end Solved;

   procedure Output_Maze(M: Maze_Type; Message: String := "") is
   begin
      if Message /= "" then
         Ada.Text_IO.Put_Line(Message);
      end if;
      for I in M'Range loop
         Ada.Text_IO.Put_Line(M(I));
      end loop;
   end Output_Maze;

   procedure Search(M: in out Maze_Type; X: X_Range; Y:Y_Range) is
   begin
      M(Y)(X) := '*';
      if Solved(X, Y) then
         Output_Maze(M, "Solution found!");
      else
         if Integer(Y)-South >= 1 and then M(Y-South)(X) = ' ' then
            Search(M, X, Y-South);
         end if;
         if Integer(Y)+South <= Y_Size and then M(Y+South)(X) = ' ' then
            Search(M, X, Y+South);
         end if;
         if Integer(X)-East >= 1 and then M(Y)(X-East) = ' ' then
            Search(M, X-East, Y);
         end if;
         if Integer(Y)+East <= Y_Size and then M(Y)(X+East) = ' ' then
            Search(M, X+East, Y);
         end if;
      end if;
      M(Y)(X) := ' ';
   end Search;

   Maze: Maze_Type;
   X: X_Range := X_Start;
   Y: Y_Range := Y_Start;

begin
   for I in 1 .. Y_Size loop
      Maze(I) := Ada.Text_IO.Get_Line;
   end loop;
   Maze(Y_Start)(X_Start)   := ' '; 
   Maze(Y_Finish)(X_Finish) := ' '; 
   Output_Maze(Maze, "The Maze:");
   Ada.Text_IO.New_Line;

   Search(Maze, X, Y) ; 
                        
end Maze_Solver;