Grid with obstacles coverage algorithm - algorithm

I have to find an algorithm for a robot Agent to do the following (I'm sorry, I don't really know how to call it):
The robot is on a 10x10 grid with obstacles (each square is either a obstacle or traversable)
The robot has a bump sensor : it activates when the robot hits an obstacle.
On the grid there are carrots that are continously growing. There are fast-growing squares and slow growing squares.
Each step, the robot can : advance or turn 90° right or left or stay in place
The locations of the carrots and obstacles are not know before hand
The carrots continue growing while the robot is moving (even after harvest)
Carrots grow in most squares that are not obstacles
The robot does not know if the squares are fast or slow growing
In each square there can be between 0 and 20 carrots. At each time instance, there is a probability p = 0.01 (or p = 0.02 for fast-growing squares) for the amount of carrots of a square to increment
You can measure the amount of carrots you harvest.
The goal is to get the maximum amount of carrots in 2000 steps.
Would there be a lazy/easy way to do it?
So far, I am a bit lost, as it is not a maze-solving problem. Would it be a sort a flood-filling algorithm ? Is there anything simpler ?
I'm not necessarily searching to "solve" the problem, but rather for an easy approximation if possible

It is indeed a bit of work to find a robot implementation which has the perfect strategy, given that it does not know the location and the number of the food sources.
Any given strategy of a bot might not yield the maximum possible harvest in each run. So the question is rather, which strategy is most successful over a number of simulation runs.
To find a decent strategy for a given statistical distribution of square types (P(fastFood),P(slowFood),P(obstacle)), one might come up with the following idea:
Let Bot(npatch) be a bot which looks for npatch food spots. With the strategy to eat up what it finds in the first food patch before it searches the second and so on. When it visited npatch food sources (or found no more food patches), it returns to the first one found and re-harvests.
This class of bots (Bot(npatch)) can now compete against each other in a statistically relevant number of simulation runs. Best bot is winner of the competition.
This approach can be considered inspired by genetic algorithms, yet without mixing any genes but simply iterating all of them (1..npatch). Maybe someone has an idea how to turn this idea to a fully genetic algorithm. This could involve turning to a Bot(npatch,searchStrategy) and then, having multiple genes to apply a genetic algorithm.
Whenever the parameters of the simulation change, the competition has to be repeated, obviously as depending on the number of food patches in the world, it might or might not pay off to go find yet another food patch if some food patches are known already.
The code below is written in F# and is the simulator for that question (if I got all requirements right, that is...). Writing a new bot is as simple as writing a function, which is then passed to the simulator.
Consider this my easter egg for those of you who would like to try their own bots.
The 2 bots I wrote are called "marvinRobot" which does what Marvin would do and "lazyRobot" a bot which camps on the first food source it finds.
type Square =
| Empty
| Obstacle
| Food of float * (float -> float) // available * growth
| Unknown
let rnd = new System.Random()
let grow p a =
let r = rnd.NextDouble()
if r < p then a + 1.0
else a
let slowGrowth a = grow 0.01 a
let fastGrowth a = grow 0.02 a
let eatPerTick = 1.0
let maxFoodPerSquare = 20.0
let randomPick values =
let count = List.length values
let r = rnd.Next(0,count-1)
values.Item(r)
type World = Square[,]
let randomSquare pobstacle pfood =
let r = rnd.NextDouble()
match r with
| x1 when x1 < pobstacle -> Obstacle
| x2 when x2 < (pobstacle + pfood) && x2 >= pobstacle ->
Food(rnd.NextDouble() * maxFoodPerSquare, randomPick [slowGrowth; fastGrowth])
| _ -> Empty
let createRandomWorld n pobstacle pfood =
Array2D.init n n (fun col row -> randomSquare pobstacle pfood)
let createUnknownWorld n =
Array2D.create n n Unknown
type Position = { Column : int; Row : int }
type RoboState = { Memory : Square[,]; Pos : Position; Heading : Position }
type RoboAction =
| TurnRight
| TurnLeft
| MoveOne
| Eat
| Idle
type RoboActor = World -> RoboState -> RoboAction
let right heading : Position =
match heading with
| { Column = 0; Row = 1 } -> { Column = -1; Row = 0 }
| { Column = -1; Row = 0 } -> { Column = 0; Row = -1 }
| { Column = 0; Row = -1 } -> { Column = 1; Row = 0 }
| { Column = 1; Row = 0 } -> { Column = 0; Row = 1 }
| _ -> failwith "Invalid heading!"
let left heading : Position =
match heading with
| { Column = -1; Row = 0 } -> { Column = 0; Row = 1 }
| { Column = 0; Row = -1 } -> { Column = -1; Row = 0 }
| { Column = 1; Row = 0 } -> { Column = 0; Row = -1 }
| { Column = 0; Row = 1 } -> { Column = 1; Row = 0 }
| _ -> failwith "Invalid heading!"
let checkAccess n position =
let inRange v = v >= 0 && v < n
(inRange position.Column) && (inRange position.Row)
let tickWorld world =
world
|> Array2D.map
(fun sq ->
match sq with
| Empty -> Empty
| Obstacle -> Obstacle
| Food(a,r) -> Food(min (r a) maxFoodPerSquare, r)
| Unknown -> Unknown
)
let rec step robot world roboState i imax acc =
if i < imax then
let action = robot world roboState
match action with
| TurnRight ->
let rs1 = { roboState with Heading = right roboState.Heading }
let wrld1 = tickWorld world
step robot wrld1 rs1 (i+1) imax acc
| TurnLeft ->
let rs1 = { roboState with Heading = left roboState.Heading }
let wrld1 = tickWorld world
step robot wrld1 rs1 (i+1) imax acc
| MoveOne ->
let rs1 =
let c =
{ Column = roboState.Pos.Column + roboState.Heading.Column
Row = roboState.Pos.Row + roboState.Heading.Row
}
if checkAccess (Array2D.length1 world) c
then
match world.[c.Column,c.Row] with
| Obstacle ->
roboState.Memory.[c.Column,c.Row] <- Obstacle
roboState
| _ -> { roboState with Pos = c }
else
roboState
let wrld1 = tickWorld world
step robot wrld1 rs1 (i+1) imax acc
| Eat ->
let eat,acc1 =
match world.[roboState.Pos.Column,roboState.Pos.Row] with
| Empty -> Empty,acc
| Obstacle -> Obstacle,acc
| Food(a,r) ->
let eaten = if a >= eatPerTick then eatPerTick else 0.0
printfn "eating %f carrots" eaten
Food(a - eaten, r),eaten + acc
| Unknown -> Unknown,acc
world.[roboState.Pos.Column,roboState.Pos.Row] <- eat
let wrld1 = tickWorld world
step robot wrld1 roboState (i+1) imax acc1
| Idle ->
step robot (tickWorld world) roboState (i+1) imax acc
else
acc
let initRoboState n =
{ Memory = createUnknownWorld n;
Pos = { Column = 0; Row = 0;};
Heading = {Column = 1; Row = 0}
}
let simulate n pobstacle pfood imax robot =
let w0 = createRandomWorld n pobstacle pfood
let r0 = initRoboState n
printfn "World: %A" w0
printfn "Initial Robo State: %A" r0
let result = step robot w0 r0 0 imax 0.0
printfn "Final Robo State: %A" r0
result
// Not that Marvin would care, but the rule for this simulator is that the
// bot may only inspect the square in the world at the current position.
// This means, IT CANNOT SEE the neighboring squares.
// This means, that if there is a obstacle next to current square,
// it costs a simulation tick to find out, trying to bump against it.
// Any access to other squares in world is considered cheating!
// world is passed in spite of all said above to allow for alternate rules.
let marvinRobot world roboState =
Idle
// Tries to find a square with food, then stays there, eating when there is something to eat.
let lazyRobot (world : World) (roboState : RoboState) =
let search() =
let status action : RoboAction =
match action with
| TurnLeft -> printfn "%A TurnLeft at %A (heading: %A)" world.[roboState.Pos.Column,roboState.Pos.Row] roboState.Pos roboState.Heading
| TurnRight -> printfn "%ATurnRight at %A (heading: %A)" world.[roboState.Pos.Column,roboState.Pos.Row] roboState.Pos roboState.Heading
| MoveOne -> printfn "%A MoveOne at %A (heading: %A)" world.[roboState.Pos.Column,roboState.Pos.Row] roboState.Pos roboState.Heading
| Idle -> printfn "%A Idle at %A (heading: %A)" world.[roboState.Pos.Column,roboState.Pos.Row] roboState.Pos roboState.Heading
| Eat -> printfn "%A Eat at %A (heading: %A)" world.[roboState.Pos.Column,roboState.Pos.Row] roboState.Pos roboState.Heading
action
let neighbors =
[ roboState.Heading, MoveOne;
(roboState.Heading |> right),TurnRight;
(roboState.Heading |> left),TurnLeft;
(roboState.Heading |> right |> right),TurnRight
]
|> List.map (fun (p,a) -> (p.Column,p.Row),a)
|> List.map (fun ((c,r),a) -> (roboState.Pos.Column + c,roboState.Pos.Row + r),a)
|> List.filter (fun ((c,r),a) -> checkAccess (Array2D.length1 world){Position.Column = c; Row = r})
|> List.sortBy (fun ((c,r),a) -> match roboState.Memory.[c,r] with | Food(_,_) -> 0 | Unknown -> 1 | Empty -> 2 | Obstacle -> 3)
|> List.map (fun ((c,r),a) -> { Column = c; Row = r},a)
if neighbors.IsEmpty then failwith "It's a trap!" // can happen if bot is surrounded by obstacles, e.g. in a corner
else
let p,a = neighbors.Head
status a
roboState.Memory.[roboState.Pos.Column, roboState.Pos.Row] <-
world.[roboState.Pos.Column,roboState.Pos.Row]
match world.[roboState.Pos.Column,roboState.Pos.Row] with
| Food(a,_) ->
printfn "Found food at %A" roboState.Pos
Eat
| _ ->
search()
//simulate 10 0.1 0.05 2000 marvinRobot
simulate 10 0.1 0.1 2000 lazyRobot
Last not least a tip: if you simulate with 0.0 food patches, your bot should have visited all squares on the map. If it fails to do that, it is for sure not a good bot ;)

Related

How to improve performance with F# idioms

I'm using this course on Machine-Learning to learn F# at the same time. I've done the following homework exercise which is the first exercise of the second week:
Run a computer simulation for flipping 1,000 virtual fair coins. Flip
each coin independently 10 times. Focus on 3 coins as follows: c1
is the first coin flipped, crand is a coin chosen randomly from
the 1,000, and cmin is the coin which had the minimum frequency of
heads (pick the earlier one in case of a tie).
Let ν1 , νrand
, and νmin be the fraction of heads obtained for the 3 respective
coins out of the 10 tosses. Run the experiment 100,000 times in order
to get a full distribution of ν1 , νrand, and νmin (note that c rand
and c min will change from run to run).
What is the average value of νmin?
I have produced the following code, which works fine and gives the correct answer:
let private rnd = System.Random()
let FlipCoin() = rnd.NextDouble() > 0.5
let FlipCoinNTimes N = List.init N (fun _ -> FlipCoin())
let FlipMCoinsNTimes M N = List.init M (fun _ -> FlipCoinNTimes N)
let ObtainFrequencyOfHeads tosses =
let heads = tosses |> List.filter (fun toss -> toss = true)
float (List.length (heads)) / float (List.length (tosses))
let GetFirstRandMinHeadsFraction allCoinsLaunchs =
let first = ObtainFrequencyOfHeads(List.head (allCoinsLaunchs))
let randomCoin = List.item (rnd.Next(List.length (allCoinsLaunchs))) allCoinsLaunchs
let random = ObtainFrequencyOfHeads(randomCoin)
let min =
allCoinsLaunchs
|> List.map (fun coin -> ObtainFrequencyOfHeads coin)
|> List.min
(first, random, min)
module Exercice1 =
let GetResult() =
Seq.init 100000 (fun _ -> FlipMCoinsNTimes 1000 10)
|> Seq.map (fun oneExperiment -> GetFirstRandMinHeadsFraction oneExperiment)
|> Seq.map (fun (first, random, min) -> min)
|> Seq.average
However, it takes roughly 4 minutes to run in my machine. I know that it is doing a lot of work, but I'm wondering if there are some modifications that could be made to optimize it.
As I'm trying lo learn F#, I'm asking for optimizations that use F# idioms, not to change the code to a C-style.
Feel free to suggest any kind of improvement, in style, good practices, etc.
[UPDATE]
I have written some code to compare the proposed solutions, it is accesible here.
These are the results:
Base - result: 0.037510, time elapsed: 00:00:55.1274883, improvement:
0.99 x
Matthew Mcveigh - result: 0.037497, time elapsed: 00:00:15.1682052, improvement: 3.61 x
Fyodor Soikin - result:0.037524, time elapsed: 00:01:29.7168787, improvement: 0.61 x
GuyCoder - result: 0.037645, time elapsed: 00:00:02.0883482, improvement: 26.25 x
GuyCoder MathNet- result: 0.037666, time elapsed:
00:00:24.7596117, improvement: 2.21 x
TheQuickBrownFox - result:
0.037494, time elapsed: 00:00:34.2831239, improvement: 1.60 x
The winner concerning the improvement in time is the GuyCoder, so I will accept his answer. However, I find that his code is more difficult to understand.
Allocating a large amount of lists up front is heavy work, the algorithm can be processed online e.g. via sequences or recursion. I transformed all the work into tail recursive functions for some raw speed (will be transformed into loops by the compiler)
not guaranteed to be 100% correct, but hopefully gives you a gist of where I was going with it:
let private rnd = System.Random()
let flipCoin () = rnd.NextDouble() > 0.5
let frequencyOfHeads flipsPerCoin =
let rec countHeads numHeads i =
if i < flipsPerCoin then
let isHead = flipCoin ()
countHeads (if isHead then numHeads + 1 else numHeads) (i + 1)
else
float numHeads
countHeads 0 0 / float flipsPerCoin
let getFirstRandMinHeadsFraction numCoins flipsPerCoin =
let randomCoinI = rnd.Next numCoins
let rec run first random min i =
if i < numCoins then
let frequency = frequencyOfHeads flipsPerCoin
let first = if i = 0 then frequency else first
let random = if i = randomCoinI then frequency else random
let min = if min > frequency then frequency else min
run first random min (i + 1)
else
(first, random, min)
run 0.0 0.0 System.Double.MaxValue 0
module Exercice1 =
let getResult () =
let iterations, numCoins, numFlips = 100000, 1000, 10
let getMinFromExperiment () =
let (_, _, min) = getFirstRandMinHeadsFraction numCoins numFlips
min
let rec sumMinFromExperiments i sumOfMin =
if i < iterations then
sumMinFromExperiments (i + 1) (sumOfMin + getMinFromExperiment ())
else
sumOfMin
let sum = sumMinFromExperiments 0 0.0
sum / float iterations
Running your code on my computer and timing I get:
seconds: 68.481918
result: 0.47570994
Running my code on my computer and timing I get:
seconds: 14.003861
vOne: 0.498963
vRnd: 0.499793
vMin: 0.037675
with vMin being closest to the correct answer of b being 0.01
That is almost 5x faster.
I did not tinker with each method and data structure to figure out why and what worked, I just used many decades of experience to guide me. Clearly not storing the intermediate values but just the results is a big improvement. Specifically coinTest just returns the number of heads which is an int and not a list of the results. Also instead of getting a random number for each coin flip but getting a random number for each coin and then using each part of that random number as a coin flip is advantageous. That saves number of flips - 1 calls to a function. Also I avoided using float values until the very end; I don't consider that saving time on the CPU, but it did simplify the thought process of thinking only in int which allowed me to concentrate on other efficiencies. I know that may sound weird but the less I have to think about the better the answers I get. I also only ran coinTest when it was necessary, e.g. only the first coin, only the random coin, and looked for all tails as an exit condition.
namespace Workspace
module main =
[<EntryPoint>]
let main argv =
let rnd = System.Random()
let randomPick (limit : int) : int = rnd.Next(limit) // [0 .. limit) it's a Python habit
let numberOfCoins = 1000
let numberOfFlips = 10
let numberOfExperiements = 100000
let coinTest (numberOfFlips : int) : int =
let rec countHeads (flips : int) bitIndex (headCount : int) : int =
if bitIndex < 0 then headCount
else countHeads (flips >>> 1) (bitIndex-1) (headCount + (flips &&& 0x01))
countHeads (randomPick ((pown 2 numberOfFlips) - 1)) numberOfFlips 0
let runExperiement (numberOfCoins : int) (numberOfFlips : int) : (int * int * int) =
let (randomCoin : int) = randomPick numberOfCoins
let rec testCoin coinIndex (cFirst, cRnd, cMin, cFirstDone, cRanDone, cMinDone) : (int * int * int) =
if (coinIndex < numberOfCoins) then
if (not cFirstDone || not cRanDone || not cMinDone) then
if (cFirstDone && cMinDone && (coinIndex <> randomCoin)) then
testCoin (coinIndex+1) (cFirst, cRnd, cMin, cFirstDone, cRanDone, cMinDone)
else
let headsTotal = coinTest numberOfFlips
let (cFirst, cRnd, cMin, cFirstDone, cRanDone, cMinDone) =
let cFirst = if coinIndex = 0 then headsTotal else cFirst
let cRnd = if coinIndex = randomCoin then headsTotal else cRnd
let cMin = if headsTotal < cMin then headsTotal else cMin
let cRanDone = if (coinIndex >= randomCoin) then true else cRanDone
let cMinDone = if (headsTotal = 0) then true else cMinDone
(cFirst, cRnd, cMin, true, cRanDone, cMinDone)
testCoin (coinIndex+1) (cFirst, cRnd, cMin, cFirstDone, cRanDone, cMinDone)
else
(cFirst, cRnd, cMin)
else
(cFirst, cRnd, cMin)
testCoin 0 (-1,-1,10, false, false, false)
let runExperiements (numberOfExperiements : int) (numberOfCoins : int) ( numberOfFlips : int) =
let rec accumateExperiements index aOne aRnd aMin : (int * int * int) =
let (cOne,cRnd,cMin) = runExperiement numberOfCoins numberOfFlips
if index > numberOfExperiements then (aOne, aRnd, aMin)
else accumateExperiements (index + 1) (aOne + cOne) (aRnd + cRnd) (aMin + cMin)
let (aOne, aRnd, aMin) = accumateExperiements 0 0 0 0
let (vOne : double) = (double)(aOne) / (double)numberOfExperiements / (double)numberOfFlips
let (vRnd : double) = (double)(aRnd) / (double)numberOfExperiements / (double)numberOfFlips
let (vMin : double) = (double)(aMin) / (double)numberOfExperiements / (double)numberOfFlips
(vOne, vRnd, vMin)
let timeIt () =
let stopWatch = System.Diagnostics.Stopwatch.StartNew()
let (vOne, vRnd, vMin) = runExperiements numberOfExperiements numberOfCoins numberOfFlips
stopWatch.Stop()
printfn "seconds: %f" (stopWatch.Elapsed.TotalMilliseconds / 1000.0)
printfn "vOne: %A" vOne
printfn "vRnd: %A" vRnd
printfn "vMin: %A" vMin
timeIt ()
printf "Press any key to exit: "
System.Console.ReadKey() |> ignore
printfn ""
0 // return an integer exit code
========================================================================
This is just an intermediate answer because I inquired if the OP considered using MathNet Numerics idiomatic F# and the OP wanted to see what that looked like. After running his version and this first cut version on my machine the OP version is faster. OP: 75 secs, mine: 84 secs
namespace Workspace
open MathNet.Numerics.LinearAlgebra
module main =
[<EntryPoint>]
let main argv =
let rnd = System.Random()
let flipCoin() =
let head = rnd.NextDouble() > 0.5
if head then 1.0 else 0.0
let numberOfCoins = 1000
let numberOfFlips = 10
let numberOfExperiements = 100000
let numberOfValues = 3
let randomPick (limit : int) : int = rnd.Next(limit) // [0 .. limit) it's a Python habit
let headCount (m : Matrix<float>) (coinIndex : int) : int =
System.Convert.ToInt32((m.Row coinIndex).Sum())
let minHeads (m : Matrix<float>) (numberOfCoins : int) (numberOfFlips : int) : int =
let rec findMinHeads currentCoinIndex minHeadsCount minHeadsIndex =
match currentCoinIndex,minHeadsCount with
| -1,_ -> minHeadsCount
| _,0 -> minHeadsCount // Can't get less than zero so stop searching.
| _ ->
let currentMinHeadCount = (headCount m currentCoinIndex)
let nextIndex = currentCoinIndex - 1
if currentMinHeadCount < minHeadsCount
then findMinHeads nextIndex currentMinHeadCount currentCoinIndex
else findMinHeads nextIndex minHeadsCount minHeadsIndex
findMinHeads (numberOfCoins - 1) numberOfFlips -1
// Return the values for cOne, cRnd, and cMin as int values.
// Will do division on final sum of experiments instead of after each experiment.
let runExperiement (numberOfCoins : int) (numberOfFlips : int) : (int * int * int) =
let (flips : Matrix<float>) = DenseMatrix.init numberOfCoins numberOfFlips (fun i j -> flipCoin())
let cOne = headCount flips 0
let cRnd = headCount flips (randomPick numberOfCoins)
let cMin = minHeads flips numberOfCoins numberOfFlips
(cOne,cRnd,cMin)
let runExperiements (numberOfExperiements : int) (numberOfCoins : int) (numberOfFlips : int) : (int [] * int [] * int []) =
let (cOneArray : int[]) = Array.create numberOfExperiements 0
let (cRndArray : int[]) = Array.create numberOfExperiements 0
let (cMinArray : int[]) = Array.create numberOfExperiements 0
for i = 0 to (numberOfExperiements - 1) do
let (cOne,cRnd,cMin) = runExperiement numberOfCoins numberOfFlips
cOneArray.[i] <- cOne
cRndArray.[i] <- cRnd
cMinArray.[i] <- cMin
(cOneArray, cRndArray, cMinArray)
let (cOneArray, cRndArray, cMinArray) = runExperiements numberOfExperiements numberOfCoins numberOfFlips
let (vOne : double) = (double)(Array.sum cOneArray) / (double)numberOfExperiements / (double)numberOfFlips
let (vRnd : double) = (double)(Array.sum cRndArray) / (double)numberOfExperiements / (double)numberOfFlips
let (vMin : double) = (double)(Array.sum cMinArray) / (double)numberOfExperiements / (double)numberOfFlips
printfn "vOne: %A" vOne
printfn "vRnd: %A" vRnd
printfn "vMin: %A" vMin
Halfway through the coding I realized I could do all of the calculations using just int, it was only the last calculations that generated the percentages that needed to be a float or double and even then that is only because the list of answers is a percentage; in theory the numbers can be compared as int to get the same understanding. If I use only int then I would have to create an int Matrix type and that is more work than I want to do. When I get time I will switch the MathNet Matrix to an F# Array2D or something similar and check that. Note if you tag this with MathNet then the maintainer of MathNet might answer (Christoph Rüegg)
I made an change to this method and it is faster by 5 seconds.
// faster
let minHeads (m : Matrix<float>) (numberOfCoins : int) (numberOfFlips : int) : int =
let (mins : float[]) = m.FoldByRow((fun (x : float) y -> x + y), 0.0)
let (minHead : float) = Array.min mins
System.Convert.ToInt32(minHead)
I tried to find the smallest possible changes to your code to make it faster.
The biggest performance improvement I found was by changing the ObtainFrequencyOfHeads function so that it counts true values in the collection instead of creating an intermediate filtered collection and then counting that. I did this by using fold:
let ObtainFrequencyOfHeads tosses =
let heads = tosses |> List.fold (fun state t -> if t then state + 1 else state) 0
float heads / float (List.length (tosses))
Another improvement came from changing all of the lists into arrays. This was as simple as replacing every instance of List. with Array. (including the new function above).
Some might say this is less functional, because it's using a mutable collection instead of an immutable one. However, we're not mutating any arrays, just using the fact that they are cheap to create, check the length of, and look up by index. We have removed a restriction on mutation but we are still not using mutation. It is certainly idiomatic F# to use arrays for performance if required.
With both of these changes I got almost a 2x performance improvement in FSI.

Optimising F# answer for Euler #4

I have recently begun learning F#. Hoping to use it to perform any mathematically heavy algorithms in C# applications and to broaden my knowledge
I have so far avoided StackOverflow as I didn't want to see the answer to this until I came to one myself.
I want to be able to write very efficient F# code, focused on performance and then maybe in other ways, such as writing in F# concisely (number of lines etc.).
Project Euler Question 4:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
My Answer:
let IsPalindrome (x:int) = if x.ToString().ToCharArray() = Array.rev(x.ToString().ToCharArray()) then x else 0
let euler4 = [for i in [100..999] do
for j in [i..999] do yield i*j]
|> Seq.filter(fun x -> x = IsPalindrome(x)) |> Seq.max |> printf "Largest product of two 3-digit numbers is %d"
I tried using option and returning Some(x) and None in IsPalindrome but kept getting compiling errors as I was passing in an int and returning int option. I got a NullRefenceException trying to return None.Value.
Instead I return 0 if the number isn't a palindrome, these 0's go into the Sequence, unfortunately.
Maybe I could order the sequence and then get the top value? instead of using Seq.Max? Or filter out results > 1?
Would this be better? Any advice would be much appreciated, even if it's general F# advice.
Efficiency being a primary concern, using string allocation/manipulation to find a numeric palindrome seems misguided – here's my approach:
module NumericLiteralG =
let inline FromZero () = LanguagePrimitives.GenericZero
let inline FromOne () = LanguagePrimitives.GenericOne
module Euler =
let inline isNumPalindrome number =
let ten = 1G + 1G + 1G + 1G + 1G + 1G + 1G + 1G + 1G + 1G
let hundred = ten * ten
let rec findHighDiv div =
let div' = div * ten
if number / div' = 0G then div else findHighDiv div'
let rec impl n div =
div = 0G || n / div = n % ten && impl (n % div / ten) (div / hundred)
findHighDiv 1G |> impl number
let problem004 () =
{ 100 .. 999 }
|> Seq.collect (fun n -> Seq.init (1000 - n) ((+) n >> (*) n))
|> Seq.filter isNumPalindrome
|> Seq.max
Here's one way to do it:
/// handy extension for reversing a string
type System.String with
member s.Reverse() = String(Array.rev (s.ToCharArray()))
let isPalindrome x = let s = string x in s = s.Reverse()
seq {
for i in 100..999 do
for j in i..999 -> i * j
}
|> Seq.filter isPalindrome
|> Seq.max
|> printfn "The answer is: %d"
let IsPalindrom (str:string)=
let rec fn(a,b)=a>b||str.[a]=str.[b]&&fn(a+1,b-1)
fn(0,str.Length-1)
let IsIntPalindrome = (string>>IsPalindrom)
let sq={100..999}
sq|>Seq.map (fun x->sq|>Seq.map (fun y->(x,y),x*y))
|>Seq.concat|>Seq.filter (snd>>IsIntPalindrome)|>Seq.maxBy (snd)
just my solution:
let isPalin x =
x.ToString() = new string(Array.rev (x.ToString().ToCharArray()))
let isGood num seq1 = Seq.exists (fun elem -> (num % elem = 0 && (num / elem) < 999)) seq1
{998001 .. -1 .. 10000} |> Seq.filter(fun x -> isPalin x) |> Seq.filter(fun x -> isGood x {999 .. -1 .. 100}) |> Seq.nth 0
simplest way is to go from 999 to 100, because is much likley to be product of two large numbers.
j can then start from i because other way around was already tested
other optimisations would go in directions where multiplactions would go descending order, but that makes everything little more difficult. In general it is expressed as list mergeing.
Haskell (my best try in functional programming)
merge f x [] = x
merge f [] y = y
merge f (x:xs) (y:ys)
| f x y = x : merge f xs (y:ys)
| otherwise = y : merge f (x:xs) ys
compare_tuples (a,b) (c,d) = a*b >= c*d
gen_mul n = (n,n) : merge compare_tuples
( gen_mul (n-1) )
( map (\x -> (n,x)) [n-1,n-2 .. 1] )
is_product_palindrome (a,b) = x == reverse x where x = show (a*b)
main = print $ take 10 $ map ( \(a,b)->(a,b,a*b) )
$ filter is_product_palindrome $ gen_mul 9999
output (less than 1s)- first 10 palindromes =>
[(9999,9901,99000099),
(9967,9867,98344389),
(9999,9811,98100189),
(9999,9721,97200279),
(9999,9631,96300369),
(9999,9541,95400459),
(9999,9451,94500549),
(9767,9647,94222249),
(9867,9547,94200249),
(9999,9361,93600639)]
One can see that this sequence is lazy generated from large to small
Optimized version:
let Euler dgt=
let [mine;maxe]=[dgt-1;dgt]|>List.map (fun x->String.replicate x "9"|>int)
let IsPalindrom (str:string)=
let rec fn(a,b)=a>b||str.[a]=str.[b]&&fn(a+1,b-1)
fn(0,str.Length-1)
let IsIntPalindrome = (string>>IsPalindrom)
let rec fn=function
|x,y,max,a,_ when a=mine->x,y,max
|x,y,max,a,b when b=mine->fn(x,y,max,a-1,maxe)
|x,y,max,a,b->a*b|>function
|m when b=maxe&&m<max->x,y,max
|m when m>max&&IsIntPalindrome(m)->fn(a,b,m,a-1,maxe)
|m when m>max->fn(x,y,max,a,b-1)
|_->fn(x,y,max,a-1,maxe)
fn(0,0,0,maxe,maxe)
Log (switch #time on):
> Euler 2;;
Real: 00:00:00.004, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0
val it : int * int * int = (99, 91, 9009)
> Euler 3;;
Real: 00:00:00.004, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0
val it : int * int * int = (993, 913, 906609)
> Euler 4;;
Real: 00:00:00.002, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : int * int * int = (9999, 9901, 99000099)
> Euler 5;;
Real: 00:00:00.702, CPU: 00:00:00.686, GC gen0: 108, gen1: 1, gen2: 0
val it : int * int * int = (99793, 99041, 1293663921) //int32 overflow
Extern to BigInteger:
let Euler dgt=
let [mine;maxe]=[dgt-1;dgt]|>List.map (fun x->new System.Numerics.BigInteger(String.replicate x "9"|>int))
let IsPalindrom (str:string)=
let rec fn(a,b)=a>b||str.[a]=str.[b]&&fn(a+1,b-1)
fn(0,str.Length-1)
let IsIntPalindrome = (string>>IsPalindrom)
let rec fn=function
|x,y,max,a,_ when a=mine->x,y,max
|x,y,max,a,b when b=mine->fn(x,y,max,a-1I,maxe)
|x,y,max,a,b->a*b|>function
|m when b=maxe&&m<max->x,y,max
|m when m>max&&IsIntPalindrome(m)->fn(a,b,m,a-1I,maxe)
|m when m>max->fn(x,y,max,a,b-1I)
|_->fn(x,y,max,a-1I,maxe)
fn(0I,0I,0I,maxe,maxe)
Check:
Euler 5;;
Real: 00:00:02.658, CPU: 00:00:02.605, GC gen0: 592, gen1: 1, gen2: 0
val it :
System.Numerics.BigInteger * System.Numerics.BigInteger *
System.Numerics.BigInteger =
(99979 {...}, 99681 {...}, 9966006699 {...})

Filter an array or list by consecutive pairs based on a matching rule

This is probably trivial, and I do have a solution but I'm not happy with it. Somehow, (much) simpler forms don't seem to work and it gets messy around the corner cases (either first, or last matching pairs in a row).
To keep it simple, let's define the matching rule as any two or more numbers that have a difference of two. Example:
> filterTwins [1; 2; 4; 6; 8; 10; 15; 17]
val it : int list = [2; 4; 6; 8; 10; 15; 17]
The code I currently use is this, which just feels sloppy and overweight:
let filterTwins list =
let func item acc =
let prevItem, resultList = acc
match prevItem, resultList with
| 0, []
-> item, []
| var, [] when var - 2 = item
-> item, item::var::resultList
| var, hd::tl when var - 2 = item && hd <> var
-> item, item::var::resultList
| var, _ when var - 2 = item
-> item, item::resultList
| _
-> item, resultList
List.foldBack func list (0, [])
|> snd
I intended my own original exercise to experiment with List.foldBack, large lists and parallel programming (which went well) but ended up messing with the "easy" part...
Guide through the answers
Daniel's last, 113 characters*, easy to follow, slow
Kvb's 2nd, 106 characters* (if I include the function), easy, but return value requires work
Stephen's 2nd, 397 characters*, long winded and comparably complex, but fastest
Abel's, 155 characters*, based on Daniel's, allows duplicates (this wasn't a necessity, btw) and is relatively fast.
There were more answers, but the above were the most distinct, I believe. Hope I didn't hurt anybody's feelings by accepting Daniel's answer as solution: each and every one solution deserves to be the selected answer(!).
* counting done with function names as one character
Would this do what you want?
let filterTwins l =
let rec filter l acc flag =
match l with
| [] -> List.rev acc
| a :: b :: rest when b - 2 = a ->
filter (b::rest) (if flag then b::acc else b::a::acc) true
| _ :: t -> filter t acc false
filter l [] false
This is terribly inefficient, but here's another approach using more built-in functions:
let filterTwinsSimple l =
l
|> Seq.pairwise
|> Seq.filter (fun (a, b) -> b - 2 = a)
|> Seq.collect (fun (a, b) -> [a; b])
|> Seq.distinct
|> Seq.toList
Maybe slightly better:
let filterTwinsSimple l =
seq {
for (a, b) in Seq.pairwise l do
if b - 2 = a then
yield a
yield b
}
|> Seq.distinct
|> Seq.toList
How about this?
let filterPairs f =
let rec filter keepHead = function
| x::(y::_ as xs) when f x y -> x::(filter true xs)
| x::xs ->
let rest = filter false xs
if keepHead then x::rest else rest
| _ -> []
filter false
let test = filterPairs (fun x y -> y - x = 2) [1; 2; 4; 6; 8; 10; 15; 17]
Or if all of your list's items are unique, you could do this:
let rec filterPairs f s =
s
|> Seq.windowed 2
|> Seq.filter (fun [|a;b|] -> f a b)
|> Seq.concat
|> Seq.distinct
let test = filterPairs (fun x y -> y - x = 2) [1; 2; 4; 6; 8; 10; 15; 17]
EDIT
Or here's another alternative which I find elegant. First define a function for breaking a list into a list of groups of consecutive items satisfying a predicate:
let rec groupConsec f = function
| [] -> []
| x::(y::_ as xs) when f x y ->
let (gp::gps) = groupConsec f xs
(x::gp)::gps
| x::xs -> [x]::(groupConsec f xs)
Then, build your function by collecting all results back together, discarding any singletons:
let filterPairs f =
groupConsec f
>> List.collect (function | [_] -> [] | l -> l)
let test = filterPairs (fun x y -> y - x = 2) [1; 2; 4; 6; 8; 10; 15; 17]
The following solution is in the spirit of your own, but I use a discriminate union to encapsulate aspects of the algorithm and reign in the madness a bit:
type status =
| Keep of int
| Skip of int
| Tail
let filterTwins xl =
(Tail, [])
|> List.foldBack
(fun cur (prev, acc) ->
match prev with
| Skip(prev) when prev - cur = 2 -> (Keep(cur), cur::prev::acc)
| Keep(prev) when prev - cur = 2 -> (Keep(cur), cur::acc)
| _ -> (Skip(cur), acc))
xl
|> snd
Here's another solution which uses a similar discriminate union strategy as my other answer but it works on sequences lazily so you can watch those twin (primes?) roll in as they come:
type status =
| KeepTwo of int * int
| KeepOne of int
| SkipOne of int
| Head
let filterTwins xl =
let xl' =
Seq.scan
(fun prev cur ->
match prev with
| KeepTwo(_,prev) | KeepOne prev when cur - prev = 2 ->
KeepOne cur
| SkipOne prev when cur - prev = 2 ->
KeepTwo(prev,cur)
| _ ->
SkipOne cur)
Head
xl
seq {
for x in xl' do
match x with
| KeepTwo(a,b) -> yield a; yield b
| KeepOne b -> yield b
| _ -> ()
}
for completeness sake, I'll answer this with what I eventually came up with, based on the friendly suggestions in this thread.
The benefits of this approach are that it doesn't need Seq.distinct, which I believe is an improvement as it allows for duplicates. However, it still needs List.rev which doesn't make it the fastest. Nor is it the most succinct code (see comparison of solution in question itself).
let filterTwins l =
l
|> Seq.pairwise
|> Seq.fold (fun a (x, y) ->
if y - x = 2 then (if List.head a = x then y::a else y::x::a)
else a) [0]
|> List.rev
|> List.tail

Learning F# - printing prime numbers

Yesterday I started looking at F# during some spare time. I thought I would start with the standard problem of printing out all the prime numbers up to 100. Heres what I came up with...
#light
open System
let mutable divisable = false
let mutable j = 2
for i = 2 to 100 do
j <- 2
while j < i do
if i % j = 0 then divisable <- true
j <- j + 1
if divisable = false then Console.WriteLine(i)
divisable <- false
The thing is I feel like I have approached this from a C/C# perspective and not embraced the true functional language aspect.
I was wondering what other people could come up with - and whether anyone has any tips/pointers/suggestions. I feel good F# content is hard to come by on the web at the moment, and the last functional language I touched was HOPE about 5 years ago in university.
Here is a simple implementation of the Sieve of Eratosthenes in F#:
let rec sieve = function
| (p::xs) -> p :: sieve [ for x in xs do if x % p > 0 then yield x ]
| [] -> []
let primes = sieve [2..50]
printfn "%A" primes // [2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47]
This implementation won't work for very large lists but it illustrates the elegance of a functional solution.
Using a Sieve function like Eratosthenes is a good way to go. Functional languages work really well with lists, so I would start with that in mind for struture.
On another note, functional languages work well constructed out of functions (heh). For a functional language "feel" I would build a Sieve function and then call it to print out the primes. You could even split it up--one function builds the list and does all the work and one goes through and does all the printing, neatly separating functionality.
There's a couple of interesting versions here.
And there are well known implementations in other similar languages. Here's one in OCAML that beats one in C.
Here are my two cents:
let rec primes =
seq {
yield 2
yield! (Seq.unfold (fun i -> Some(i, i + 2)) 3)
|> Seq.filter (fun p ->
primes
|> Seq.takeWhile (fun i -> i * i <= p)
|> Seq.forall (fun i -> p % i <> 0))
}
for i in primes do
printf "%d " i
Or maybe this clearer version of the same thing as isprime is defined as a separate function:
let rec isprime x =
primes
|> Seq.takeWhile (fun i -> i*i <= x)
|> Seq.forall (fun i -> x%i <> 0)
and primes =
seq {
yield 2
yield! (Seq.unfold (fun i -> Some(i,i+2)) 3)
|> Seq.filter isprime
}
You definitely do not want to learn from this example, but I wrote an F# implementation of a NewSqueak sieve based on message passing:
type 'a seqMsg =
| Die
| Next of AsyncReplyChannel<'a>
type primes() =
let counter(init) =
MailboxProcessor.Start(fun inbox ->
let rec loop n =
async { let! msg = inbox.Receive()
match msg with
| Die -> return ()
| Next(reply) ->
reply.Reply(n)
return! loop(n + 1) }
loop init)
let filter(c : MailboxProcessor<'a seqMsg>, pred) =
MailboxProcessor.Start(fun inbox ->
let rec loop() =
async {
let! msg = inbox.Receive()
match msg with
| Die ->
c.Post(Die)
return()
| Next(reply) ->
let rec filter' n =
if pred n then async { return n }
else
async {let! m = c.AsyncPostAndReply(Next)
return! filter' m }
let! testItem = c.AsyncPostAndReply(Next)
let! filteredItem = filter' testItem
reply.Reply(filteredItem)
return! loop()
}
loop()
)
let processor = MailboxProcessor.Start(fun inbox ->
let rec loop (oldFilter : MailboxProcessor<int seqMsg>) prime =
async {
let! msg = inbox.Receive()
match msg with
| Die ->
oldFilter.Post(Die)
return()
| Next(reply) ->
reply.Reply(prime)
let newFilter = filter(oldFilter, (fun x -> x % prime <> 0))
let! newPrime = oldFilter.AsyncPostAndReply(Next)
return! loop newFilter newPrime
}
loop (counter(3)) 2)
member this.Next() = processor.PostAndReply( (fun reply -> Next(reply)), timeout = 2000)
interface System.IDisposable with
member this.Dispose() = processor.Post(Die)
static member upto max =
[ use p = new primes()
let lastPrime = ref (p.Next())
while !lastPrime <= max do
yield !lastPrime
lastPrime := p.Next() ]
Does it work?
> let p = new primes();;
val p : primes
> p.Next();;
val it : int = 2
> p.Next();;
val it : int = 3
> p.Next();;
val it : int = 5
> p.Next();;
val it : int = 7
> p.Next();;
val it : int = 11
> p.Next();;
val it : int = 13
> p.Next();;
val it : int = 17
> primes.upto 100;;
val it : int list
= [2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71;
73; 79; 83; 89; 97]
Sweet! :)
Simple but inefficient suggestion:
Create a function to test whether a single number is prime
Create a list for numbers from 2 to 100
Filter the list by the function
Compose the result with another function to print out the results
To make this efficient you really want to test for a number being prime by checking whether or not it's divisible by any lower primes, which will require memoisation. Probably best to wait until you've got the simple version working first :)
Let me know if that's not enough of a hint and I'll come up with a full example - thought it may not be until tonight...
Here is my old post at HubFS about using recursive seq's to implement prime number generator.
For case you want fast implementation, there is nice OCaml code by Markus Mottl
P.S. if you want to iterate prime number up to 10^20 you really want to port primegen by D. J. Bernstein to F#/OCaml :)
While solving the same problem, I have implemented Sieve of Atkins in F#. It is one of the most efficient modern algorithms.
// Create sieve
let initSieve topCandidate =
let result = Array.zeroCreate<bool> (topCandidate + 1)
Array.set result 2 true
Array.set result 3 true
Array.set result 5 true
result
// Remove squares of primes
let removeSquares sieve topCandidate =
let squares =
seq { 7 .. topCandidate}
|> Seq.filter (fun n -> Array.get sieve n)
|> Seq.map (fun n -> n * n)
|> Seq.takeWhile (fun n -> n <= topCandidate)
for n2 in squares do
n2
|> Seq.unfold (fun state -> Some(state, state + n2))
|> Seq.takeWhile (fun x -> x <= topCandidate)
|> Seq.iter (fun x -> Array.set sieve x false)
sieve
// Pick the primes and return as an Array
let pickPrimes sieve =
sieve
|> Array.mapi (fun i t -> if t then Some i else None)
|> Array.choose (fun t -> t)
// Flip solutions of the first equation
let doFirst sieve topCandidate =
let set1 = Set.ofList [1; 13; 17; 29; 37; 41; 49; 53]
let mutable x = 1
let mutable y = 1
let mutable go = true
let mutable x2 = 4 * x * x
while go do
let n = x2 + y*y
if n <= topCandidate then
if Set.contains (n % 60) set1 then
Array.get sieve n |> not |> Array.set sieve n
y <- y + 2
else
y <- 1
x <- x + 1
x2 <- 4 * x * x
if topCandidate < x2 + 1 then
go <- false
// Flip solutions of the second equation
let doSecond sieve topCandidate =
let set2 = Set.ofList [7; 19; 31; 43]
let mutable x = 1
let mutable y = 2
let mutable go = true
let mutable x2 = 3 * x * x
while go do
let n = x2 + y*y
if n <= topCandidate then
if Set.contains (n % 60) set2 then
Array.get sieve n |> not |> Array.set sieve n
y <- y + 2
else
y <- 2
x <- x + 2
x2 <- 3 * x * x
if topCandidate < x2 + 4 then
go <- false
// Flip solutions of the third equation
let doThird sieve topCandidate =
let set3 = Set.ofList [11; 23; 47; 59]
let mutable x = 2
let mutable y = x - 1
let mutable go = true
let mutable x2 = 3 * x * x
while go do
let n = x2 - y*y
if n <= topCandidate && 0 < y then
if Set.contains (n % 60) set3 then
Array.get sieve n |> not |> Array.set sieve n
y <- y - 2
else
x <- x + 1
y <- x - 1
x2 <- 3 * x * x
if topCandidate < x2 - y*y then
go <- false
// Sieve of Atkin
let ListAtkin (topCandidate : int) =
let sieve = initSieve topCandidate
[async { doFirst sieve topCandidate }
async { doSecond sieve topCandidate }
async { doThird sieve topCandidate }]
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
removeSquares sieve topCandidate |> pickPrimes
I know some don't recommend to use Parallel Async, but it did increase the speed ~20% on my 2 core (4 with hyperthreading) i5. Which is about the same increase I got using TPL.
I have tried rewriting it in functional way, getting read of loops and mutable variables, but performance degraded 3-4 times, so decided to keep this version.

Code Golf: Solve a Maze [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Here's an interesting problem to solve in minimal amounts of code. I expect the recursive solutions will be most popular.
We have a maze that's defined as a map of characters, where = is a wall, a space is a path, + is your starting point, and # is your ending point. An incredibly simple example is like so:
====
+ =
= ==
= #
====
Can you write a program to find the shortest path to solve a maze in this style, in as little code as possible?
Bonus points if it works for all maze inputs, such as those with a path that crosses over itself or with huge numbers of branches. The program should be able to work for large mazes (say, 1024x1024 - 1 MB), and how you pass the maze to the program is not important.
The "player" may move diagonally. The input maze will never have a diagonal passage, so your base set of movements will be up, down, left, right. A diagonal movement would be merely looking ahead a little to determine if a up/down and left/right could be merged.
Output must be the maze itself with the shortest path highlighted using the asterisk character (*).
Works for any (fixed-size) maze with a minimum of CPU cycles (given a big enough BFG2000). Source size is irrelevant since the compiler is incredibly efficient.
while curr.x != target.x and curr.y != target.y:
case:
target.x > curr.x : dx = 1
target.x < curr.x : dx = -1
else : dx = 0
case:
target.y > curr.y : dy = 1
target.y < curr.y : dy = -1
else : dy = 0
if cell[curr.x+dx,curr.y+dy] == wall:
destroy cell[curr.x+dx,curr.y+dy] with patented BFG2000 gun.
curr.x += dx
curr.y += dy
survey shattered landscape
F#, not very short (72 non-blank lines), but readable. I changed/honed the spec a bit; I assume the original maze is a rectangle fully surrounded by walls, I use different characters (that don't hurt my eyes), I only allow orthogonal moves (not diagonal). I only tried one sample maze. Except for a bug about flipping x and y indicies, this worked the first time, so I expect it is right (I've done nothing to validate it other than eyeball the solution on the one sample I gave it).
open System
[<Literal>]
let WALL = '#'
[<Literal>]
let OPEN = ' '
[<Literal>]
let START = '^'
[<Literal>]
let END = '$'
[<Literal>]
let WALK = '.'
let sampleMaze = #"###############
# # # #
# ^# # # ### #
# # # # # # #
# # # #
############ #
# $ #
###############"
let lines = sampleMaze.Split([|'\r';'\n'|], StringSplitOptions.RemoveEmptyEntries)
let width = lines |> Array.map (fun l -> l.Length) |> Array.max
let height = lines.Length
type BestInfo = (int * int) list * int // path to here, num steps
let bestPathToHere : BestInfo option [,] = Array2D.create width height None
let mutable startX = 0
let mutable startY = 0
for x in 0..width-1 do
for y in 0..height-1 do
if lines.[y].[x] = START then
startX <- x
startY <- y
bestPathToHere.[startX,startY] <- Some([],0)
let q = new System.Collections.Generic.Queue<_>()
q.Enqueue((startX,startY))
let StepTo newX newY (path,count) =
match lines.[newY].[newX] with
| WALL -> ()
| OPEN | START | END ->
match bestPathToHere.[newX,newY] with
| None ->
bestPathToHere.[newX,newY] <- Some((newX,newY)::path,count+1)
q.Enqueue((newX,newY))
| Some(_,oldCount) when oldCount > count+1 ->
bestPathToHere.[newX,newY] <- Some((newX,newY)::path,count+1)
q.Enqueue((newX,newY))
| _ -> ()
| c -> failwith "unexpected maze char: '%c'" c
while not(q.Count = 0) do
let x,y = q.Dequeue()
let (Some(path,count)) = bestPathToHere.[x,y]
StepTo (x+1) (y) (path,count)
StepTo (x) (y+1) (path,count)
StepTo (x-1) (y) (path,count)
StepTo (x) (y-1) (path,count)
let mutable endX = 0
let mutable endY = 0
for x in 0..width-1 do
for y in 0..height-1 do
if lines.[y].[x] = END then
endX <- x
endY <- y
printfn "Original maze:"
printfn "%s" sampleMaze
let bestPath, bestCount = bestPathToHere.[endX,endY].Value
printfn "The best path takes %d steps." bestCount
let resultMaze = Array2D.init width height (fun x y -> lines.[y].[x])
bestPath |> List.tl |> List.iter (fun (x,y) -> resultMaze.[x,y] <- WALK)
for y in 0..height-1 do
for x in 0..width-1 do
printf "%c" resultMaze.[x,y]
printfn ""
//Output:
//Original maze:
//###############
//# # # #
//# ^# # # ### #
//# # # # # # #
//# # # #
//############ #
//# $ #
//###############
//The best path takes 27 steps.
//###############
//# # #....... #
//# ^# #.# ###. #
//# .# #.# # #. #
//# .....# #. #
//############. #
//# $....... #
//###############
Python
387 Characters
Takes input from stdin.
import sys
m,n,p=sys.stdin.readlines(),[],'+'
R=lambda m:[r.replace(p,'*')for r in m]
while'#'in`m`:n+=[R(m)[:r]+[R(m)[r][:c]+p+R(m)[r][c+1:]]+R(m)[r+1:]for r,c in[(r,c)for r,c in[map(sum,zip((m.index(filter(lambda i:p in i,m)[0]),[w.find(p)for w in m if p in w][0]),P))for P in zip((-1,0,1,0),(0,1,0,-1))]if 0<=r<len(m)and 0<=c<len(m[0])and m[r][c]in'# ']];m=n.pop(0)
print''.join(R(m))
I did this sort of thing for a job interview once (it was a pre-interview programming challenge)
Managed to get it working to some degree of success and it's a fun little challenge.

Resources