More Samples
{

The Problem of the Tanks

one of Clif Pickover's Extreme Challenges 

You are a tank traveling (up, down, left, right and diagonally) through electric fields. 
If you travel through two - signs in a row, your battery is drained and you are stuck. 
If you travel through two + signs in a row, your battery overcharges and explodes. 
How can you travel from Start to End through every cell once and survive? 

        - + - + -
        + + - - +
        - + + + S
        - + E - -
        - + + - +

Run the query

    all TankTour()

}

local Symbol = P | M | B | E  //"Plus","Minus","Beginning","End"

local Map :<[0..4]->[0..4]->Symbol = 
         [[M,P,M,P,M],
          [P,P,M,M,P],
          [M,P,P,P,B],
          [M,P,E,M,M],
          [M,P,P,M,P]] 

local Board = [0..4]->[0..4]->I

pred TankTour() iff
    pos:.Board & Dupl(5,Dupl(5,0),pos) &      //Intialize all position as 0 (not visited)
    pos (2,4) := 1 &                          //First step is placing the tank at the beginning
    TankTour1(pos,2,4,2) &                    //Calculate the rest of the steps (starting at step 2)                      
    PrintFormattedSolution(pos,0)             //Simple formatted printout of the solution
                                              // (starting at row 0) 

local pred TankTour1(pos:.Board,row:<I,col:<I,step:<I)  iff
    if step <= Len(pos)*Len(pos(0)) then        // there are as many moves as board elements
        MoveTank(row,col,newrow,newcol) &
        // If the position is not visited yet, we'll assign the step number to it.
        // (Otherwise the test for position = 0 fails and forces a backtrack)
        // If the newcol, newrow are outside the arena, we'll get a backtrack as well.
        pos(newrow,newcol) = 0 & 

        // We make sure that we landed on a different square then the last one
        Map(newrow,newcol) <> Map(row,col) &

        // Only the very last step can land on the End position
        if step = Len(pos)*Len(pos(0)) then
            Map(newrow,newcol) = E 
        else
            Map(newrow,newcol) <> E 
        end &

        // If we got here, then the newcol,newrow are on the board and were never visited.
        // So we mark the place as visited and continue with trying to find the next move
        pos(newrow,newcol) := step &
        TankTour1(pos,newrow,newcol,step+1)
    end


local pred MoveTank(row:<I,col:<I,newrow:>I,newcol:>I) iff

    //  Given a tank at position row,col (marked 't'), the tank can
    //  move to eight different places:
    //
    //  +---+---+---+---+
    //  |   |   |   |   |
    //  +---+---+---+---+
    //  | 1 | 2 | 3 |   |
    //  +---+---+---+---+
    //  | 8 | T | 4 |   |
    //  +---+---+---+---+
    //  | 7 | 6 | 5 |   |
    //  +---+---+---+---+
    //  |   |   |   |   |
    //  +---+---+---+---+

    newcol =  col - 1 & newrow = row - 1 | // 1   
    newcol =  col     & newrow = row - 1 | // 2   
    newcol =  col + 1 & newrow = row - 1 | // 3   
    newcol =  col + 1 & newrow = row     | // 4   
    newcol =  col + 1 & newrow = row + 1 | // 5   
    newcol =  col     & newrow = row + 1 | // 6   
    newcol =  col - 1 & newrow = row + 1 | // 7   
    newcol =  col - 1 & newrow = row       // 8   

// Print the double array "pos" as a matrix of M rows by N columns, with each position
// formatted to two digits (no leading zeros)

local proc PrintFormattedSolution(pos:<Board,row:<I) iff
    if row < Len(pos) then 
        Print('\n') & PrintOneRow(pos(row),0) & PrintFormattedSolution(pos,row+1) 
    end

local proc PrintOneRow(r:<[0..]->I,col:<I) iff
    if col < Len(r) then
        if r(col) < 10 then 
            Print(' ')
        end &
        Print(r(col),' ') & PrintOneRow(r,col+1)
    end




This page was created by F1toHTML