Knight's tour: Difference between revisions
Content added Content deleted
Line 2,522: | Line 2,522: | ||
=={{header|Elm}}== |
=={{header|Elm}}== |
||
<lang elm> |
<lang elm>import List exposing (concatMap, foldl, head,member,filter,length,minimum,concat,map,map2,tail) |
||
⚫ | |||
import List exposing (concatMap, foldl, head,member,filter,length,minimum,concat,map,map2,tail) |
|||
import List.Extra exposing (minimumBy, andThen) |
import List.Extra exposing (minimumBy, andThen) |
||
import String exposing (join) |
import String exposing (join) |
||
import Html as H |
import Html as H |
||
import Html.Attributes as HA |
import Html.Attributes as HA |
||
import |
import Html.App exposing (program) |
||
⚫ | |||
import Svg exposing (rect, line, svg, g) |
import Svg exposing (rect, line, svg, g) |
||
import Svg.Events exposing (onClick) |
import Svg.Events exposing (onClick) |
||
Line 2,539: | Line 2,537: | ||
rowCount=20 |
rowCount=20 |
||
colCount=20 |
colCount=20 |
||
dt = 0.03 |
|||
type alias Cell = (Int, Int) |
type alias Cell = (Int, Int) |
||
type alias Model = |
type alias Model = |
||
{ path : List Cell |
{ path : List Cell |
||
, board : List Cell |
, board : List Cell |
||
} |
} |
||
type Msg = NoOp | Tick Time | SetStart Cell |
|||
type Msg |
|||
= NoOp |
|||
| Tick Time.Posix |
|||
| SetStart Cell |
|||
init : |
init : (Model,Cmd Msg) |
||
init |
init = |
||
let board = |
let board = [0..rowCount-1] `andThen` \r -> |
||
[0..colCount-1] `andThen` \c -> |
|||
[(r, c)] |
|||
(List.range 0 (colCount-1)) |
|||
|> andThen |
|||
(\c -> |
|||
[(r, c)] |
|||
) |
|||
) |
|||
path = [] |
path = [] |
||
in (Model path board, Cmd.none) |
in (Model path board, Cmd.none) |
||
view : Model -> H.Html Msg |
view : Model -> H.Html Msg |
||
view model = |
view model = |
||
let |
let |
||
showChecker row col = |
showChecker row col = |
||
rect [ x <| |
rect [ x <| toString col |
||
, y <| |
, y <| toString row |
||
, width "1" |
, width "1" |
||
, height "1" |
, height "1" |
||
, fill <| if |
, fill <| if (row + col) % 2 == 0 then "blue" else "grey" |
||
, onClick <| SetStart (row, col) |
, onClick <| SetStart (row, col) |
||
] |
] |
||
[] |
[] |
||
showMove (row0,col0) (row1,col1) = |
showMove (row0,col0) (row1,col1) = |
||
line [ x1 <| |
line [ x1 <| toString ((toFloat col0) + 0.5) |
||
, y1 <| |
, y1 <| toString ((toFloat row0) + 0.5) |
||
, x2 <| |
, x2 <| toString ((toFloat col1) + 0.5) |
||
, y2 <| |
, y2 <| toString ((toFloat row1) + 0.5) |
||
, style "stroke:yellow;stroke-width:0.05" |
, style "stroke:yellow;stroke-width:0.05" |
||
] |
] |
||
[] |
[] |
||
render |
render model = |
||
let checkers = |
let checkers = model.board `andThen` \(r,c) -> |
||
[showChecker r c] |
|||
moves = case List.tail model.path of |
|||
[showChecker r c] |
|||
) |
|||
moves = case List.tail mdl.path of |
|||
Nothing -> [] |
Nothing -> [] |
||
Just tl -> List.map2 showMove |
Just tl -> List.map2 showMove model.path tl |
||
in checkers ++ moves |
in checkers ++ moves |
||
unvisited = length model.board - length model.path |
unvisited = length model.board - length model.path |
||
center = |
center = HA.style [ ( "text-align", "center") ] |
||
in |
in |
||
H.div |
H.div |
||
[] |
[] |
||
[ H.h2 center [H.text "Knight's Tour"] |
[ H.h2 [center] [H.text "Knight's Tour"] |
||
, H.h2 center [H.text <| "Unvisited count : " ++ |
, H.h2 [center] [H.text <| "Unvisited count : " ++ toString unvisited ] |
||
, H.h2 center [H.text "(pick a square)"] |
, H.h2 [center] [H.text "(pick a square)"] |
||
, H.div |
, H.div |
||
center |
[center] |
||
[ svg |
[ svg |
||
[ version "1.1" |
[ version "1.1" |
||
, width ( |
, width (toString w) |
||
, height ( |
, height (toString h) |
||
, viewBox (join " " |
, viewBox (join " " |
||
[ |
[ toString 0 |
||
, |
, toString 0 |
||
, |
, toString colCount |
||
, |
, toString rowCount ]) |
||
] |
] |
||
[ g [] <| render model] |
[ g [] <| render model] |
||
] |
] |
||
] |
] |
||
nextMoves : Model -> Cell -> List Cell |
nextMoves : Model -> Cell -> List Cell |
||
nextMoves model (stRow,stCol) = |
nextMoves model (stRow,stCol) = |
||
let c = [ 1, 2, -1, -2] |
let c = [ 1, 2, -1, -2] |
||
km = c |
km = c `andThen` \cRow -> |
||
c `andThen` \cCol -> |
|||
( |
if abs(cRow) == abs(cCol) then [] else [(cRow,cCol)] |
||
c |
|||
|> andThen |
|||
(\cCol -> |
|||
if abs(cRow) == abs(cCol) then [] else [(cRow,cCol)] |
|||
) |
|||
) |
|||
jumps = List.map (\(kmRow,kmCol) -> (kmRow + stRow, kmCol + stCol)) km |
jumps = List.map (\(kmRow,kmCol) -> (kmRow + stRow, kmCol + stCol)) km |
||
Line 2,644: | Line 2,625: | ||
bestMove : Model -> Maybe Cell |
bestMove : Model -> Maybe Cell |
||
bestMove model = |
bestMove model = |
||
case List.head (model.path) of |
case List.head (model.path) of |
||
Nothing -> Nothing |
Nothing -> Nothing |
||
Line 2,652: | Line 2,633: | ||
update msg model = |
update msg model = |
||
let mo = case msg of |
let mo = case msg of |
||
SetStart start -> |
SetStart start -> |
||
{model | path = [start]} |
{model | path = [start]} |
||
Tick |
Tick t -> |
||
case model.path of |
case model.path of |
||
[] -> model |
[] -> model |
||
Line 2,664: | Line 2,645: | ||
subscriptions : Model -> Sub Msg |
subscriptions : Model -> Sub Msg |
||
subscriptions _ = |
subscriptions _ = |
||
Time.every |
Time.every (dt * second) Tick |
||
main = |
main = |
||
program |
|||
element |
|||
{ init = init |
{ init = init |
||
, view = view |
, view = view |
||
, update = update |
, update = update |
||
, subscriptions = subscriptions |
, subscriptions = subscriptions |
||
} |
}</lang> |
||
Link to live demo: http://dc25.github.io/knightsTourElm/ |
Link to live demo: http://dc25.github.io/knightsTourElm/ |