Add tasks for all the new languages
This commit is contained in:
parent
9dc3c2bb62
commit
bba7bfd280
13208 changed files with 134745 additions and 0 deletions
249
Task/Maze-generation/Elm/maze-generation.elm
Normal file
249
Task/Maze-generation/Elm/maze-generation.elm
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
import Maybe as M
|
||||
import Result as R
|
||||
import Matrix
|
||||
import Mouse
|
||||
import Random exposing (Seed)
|
||||
import Matrix.Random
|
||||
import Time exposing (Time, every, second)
|
||||
import Set exposing (Set, fromList)
|
||||
import List exposing (..)
|
||||
import String exposing (join)
|
||||
import Html exposing (Html, br, input, h1, h2, text, div, button)
|
||||
import Html.Events as HE
|
||||
import Html.Attributes as HA
|
||||
import Html.App exposing (program)
|
||||
import Json.Decode as JD
|
||||
import Svg
|
||||
import Svg.Attributes exposing (version, viewBox, cx, cy, r, x, y, x1, y1, x2, y2, fill,points, style, width, height, preserveAspectRatio)
|
||||
|
||||
minSide = 10
|
||||
maxSide = 40
|
||||
w = 700
|
||||
h = 700
|
||||
dt = 0.001
|
||||
|
||||
type alias Direction = Int
|
||||
down = 0
|
||||
right = 1
|
||||
|
||||
type alias Door = (Matrix.Location, Direction)
|
||||
|
||||
type State = Initial | Generating | Generated | Solved
|
||||
|
||||
type alias Model =
|
||||
{ rows : Int
|
||||
, cols : Int
|
||||
, animate : Bool
|
||||
, boxes : Matrix.Matrix Bool
|
||||
, doors : Set Door
|
||||
, current : List Matrix.Location
|
||||
, state : State
|
||||
, seedStarter : Int
|
||||
, seed : Seed
|
||||
}
|
||||
|
||||
initdoors : Int -> Int -> Set Door
|
||||
initdoors rows cols =
|
||||
let
|
||||
pairs la lb = List.concatMap (\at -> List.map ((,) at) lb) la
|
||||
downs = pairs (pairs [0..rows-2] [0..cols-1]) [down]
|
||||
rights = pairs (pairs [0..rows-1] [0..cols-2]) [right]
|
||||
in downs ++ rights |> fromList
|
||||
|
||||
initModel : Int -> Int -> Bool -> State -> Int -> Model
|
||||
initModel rows cols animate state starter =
|
||||
let rowGenerator = Random.int 0 (rows-1)
|
||||
colGenerator = Random.int 0 (cols-1)
|
||||
locationGenerator = Random.pair rowGenerator colGenerator
|
||||
(c, s)= Random.step locationGenerator (Random.initialSeed starter)
|
||||
in { rows = rows
|
||||
, cols = cols
|
||||
, animate = animate
|
||||
, boxes = Matrix.matrix rows cols (\location -> state == Generating && location == c)
|
||||
, doors = initdoors rows cols
|
||||
, current = if state == Generating then [c] else []
|
||||
, state = state
|
||||
, seedStarter = starter -- updated every Tick until maze generated.
|
||||
, seed = s
|
||||
}
|
||||
|
||||
view model =
|
||||
let
|
||||
borderLineStyle = style "stroke:green;stroke-width:0.3"
|
||||
wallLineStyle = style "stroke:green;stroke-width:0.1"
|
||||
|
||||
x1Min = x1 <| toString 0
|
||||
y1Min = y1 <| toString 0
|
||||
x1Max = x1 <| toString model.cols
|
||||
y1Max = y1 <| toString model.rows
|
||||
x2Min = x2 <| toString 0
|
||||
y2Min = y2 <| toString 0
|
||||
x2Max = x2 <| toString model.cols
|
||||
y2Max = y2 <| toString model.rows
|
||||
|
||||
borders = [ Svg.line [ x1Min, y1Min, x2Max, y2Min, borderLineStyle ] []
|
||||
, Svg.line [ x1Max, y1Min, x2Max, y2Max, borderLineStyle ] []
|
||||
, Svg.line [ x1Max, y1Max, x2Min, y2Max, borderLineStyle ] []
|
||||
, Svg.line [ x1Min, y1Max, x2Min, y2Min, borderLineStyle ] []
|
||||
]
|
||||
|
||||
doorToLine door =
|
||||
let (deltaX1, deltaY1) = if (snd door == right) then (1,0) else (0,1)
|
||||
(row, column) = fst door
|
||||
in Svg.line [ x1 <| toString (column + deltaX1)
|
||||
, y1 <| toString (row + deltaY1)
|
||||
, x2 <| toString (column + 1)
|
||||
, y2 <| toString (row + 1)
|
||||
, wallLineStyle ] []
|
||||
|
||||
doors = (List.map doorToLine <| Set.toList model.doors )
|
||||
|
||||
circleInBox (row,col) color =
|
||||
Svg.circle [ r "0.25"
|
||||
, fill (color)
|
||||
, cx (toString (toFloat col + 0.5))
|
||||
, cy (toString (toFloat row + 0.5))
|
||||
] []
|
||||
|
||||
showUnvisited location box =
|
||||
if box then [] else [ circleInBox location "yellow" ]
|
||||
|
||||
unvisited = model.boxes
|
||||
|> Matrix.mapWithLocation showUnvisited
|
||||
|> Matrix.flatten
|
||||
|> concat
|
||||
|
||||
current =
|
||||
case head model.current of
|
||||
Nothing -> []
|
||||
Just c -> [circleInBox c "black"]
|
||||
|
||||
maze =
|
||||
if model.animate || model.state /= Generating
|
||||
then [ Svg.g [] <| doors ++ borders ++ unvisited ++ current ]
|
||||
else [ Svg.g [] <| borders ]
|
||||
in
|
||||
div
|
||||
[]
|
||||
[ h2 [centerTitle] [text "Maze Generator"]
|
||||
, div
|
||||
[floatLeft]
|
||||
( slider "rows" minSide maxSide model.rows SetRows
|
||||
++ [ br [] [] ]
|
||||
|
||||
++ slider "cols" minSide maxSide model.cols SetCols
|
||||
++ [ br [] [] ]
|
||||
|
||||
++ checkbox "Animate" model.animate SetAnimate
|
||||
++ [ br [] [] ]
|
||||
|
||||
++ [ button
|
||||
[ HE.onClick Generate ]
|
||||
[ text "Generate"]
|
||||
] )
|
||||
, div
|
||||
[floatLeft]
|
||||
[ Svg.svg
|
||||
[ version "1.1"
|
||||
, width (toString w)
|
||||
, height (toString h)
|
||||
, viewBox (join " "
|
||||
[ 0 |> toString
|
||||
, 0 |> toString
|
||||
, model.cols |> toString
|
||||
, model.rows |> toString ])
|
||||
]
|
||||
maze
|
||||
]
|
||||
]
|
||||
|
||||
checkbox label checked msg =
|
||||
[ input
|
||||
[ HA.type' "checkbox"
|
||||
, HA.checked checked
|
||||
, HE.on "change" (JD.map msg HE.targetChecked)
|
||||
]
|
||||
[]
|
||||
, text label
|
||||
]
|
||||
|
||||
slider name min max current msg =
|
||||
[ input
|
||||
[ HA.value (if current >= min then current |> toString else "")
|
||||
, HE.on "input" (JD.map msg HE.targetValue )
|
||||
, HA.type' "range"
|
||||
, HA.min <| toString min
|
||||
, HA.max <| toString max
|
||||
]
|
||||
[]
|
||||
, text <| name ++ "=" ++ (current |> toString)
|
||||
]
|
||||
|
||||
floatLeft = HA.style [ ("float", "left") ]
|
||||
centerTitle = HA.style [ ( "text-align", "center") ]
|
||||
|
||||
unvisitedNeighbors : Model -> Matrix.Location -> List Matrix.Location
|
||||
unvisitedNeighbors model (row,col) =
|
||||
[(row, col-1), (row-1, col), (row, col+1), (row+1, col)]
|
||||
|> List.filter (\l -> fst l >= 0 && snd l >= 0 && fst l < model.rows && snd l < model.cols)
|
||||
|> List.filter (\l -> (Matrix.get l model.boxes) |> M.withDefault False |> not)
|
||||
|
||||
updateModel' : Model -> Int -> Model
|
||||
updateModel' model t =
|
||||
case head model.current of
|
||||
Nothing -> {model | state = Generated, seedStarter = t }
|
||||
Just prev ->
|
||||
let neighbors = unvisitedNeighbors model prev
|
||||
in if (length neighbors) > 0 then
|
||||
let (neighborIndex, seed) = Random.step (Random.int 0 (length neighbors-1)) model.seed
|
||||
next = head (drop neighborIndex neighbors) |> M.withDefault (0,0)
|
||||
boxes = Matrix.set next True model.boxes
|
||||
dir = if fst prev == fst next then right else down
|
||||
doorCell = if ( (dir == down) && (fst prev < fst next))
|
||||
|| (dir == right ) && (snd prev < snd next) then prev else next
|
||||
doors = Set.remove (doorCell, dir) model.doors
|
||||
in {model | boxes=boxes, doors=doors, current=next :: model.current, seed=seed, seedStarter = t}
|
||||
else
|
||||
let tailCurrent = tail model.current |> M.withDefault []
|
||||
in updateModel' {model | current = tailCurrent} t
|
||||
|
||||
updateModel : Msg -> Model -> Model
|
||||
updateModel msg model =
|
||||
let stringToCellCount s =
|
||||
let v' = String.toInt s |> R.withDefault minSide
|
||||
in if v' < minSide then minSide else v'
|
||||
in case msg of
|
||||
Tick tf ->
|
||||
let t = truncate tf
|
||||
in
|
||||
if (model.state == Generating) then updateModel' model t
|
||||
else { model | seedStarter = t }
|
||||
|
||||
Generate ->
|
||||
initModel model.rows model.cols model.animate Generating model.seedStarter
|
||||
|
||||
SetRows countString ->
|
||||
initModel (stringToCellCount countString) model.cols model.animate Initial model.seedStarter
|
||||
|
||||
SetCols countString ->
|
||||
initModel model.rows (stringToCellCount countString) model.animate Initial model.seedStarter
|
||||
|
||||
SetAnimate b ->
|
||||
{ model | animate = b }
|
||||
|
||||
NoOp -> model
|
||||
|
||||
type Msg = NoOp | Tick Time | Generate | SetRows String | SetCols String | SetAnimate Bool
|
||||
|
||||
subscriptions model = every (dt * second) Tick
|
||||
|
||||
main =
|
||||
let
|
||||
update msg model = (updateModel msg model, Cmd.none)
|
||||
init = (initModel 21 36 False Initial 0, Cmd.none)
|
||||
in program
|
||||
{ init = init
|
||||
, view = view
|
||||
, update = update
|
||||
, subscriptions = subscriptions
|
||||
}
|
||||
130
Task/Maze-generation/FreeBASIC/maze-generation.freebasic
Normal file
130
Task/Maze-generation/FreeBASIC/maze-generation.freebasic
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
' version 04-12-2016
|
||||
' compile with: fbc -s console
|
||||
' when generating a big maze it's possible to run out of stack space
|
||||
' increase stack with the -t xxxx (xxxx is the amount you want in Kbytes)
|
||||
|
||||
ReDim Shared As String d() ' directions
|
||||
ReDim Shared As ULong c() ' cell's
|
||||
|
||||
Sub cell(x As ULong, y As ULong, s As ULong)
|
||||
|
||||
Dim As ULong x1, y1, di_n
|
||||
c(x,y) = 1 ' mark as visited
|
||||
|
||||
Do
|
||||
Dim As String di = d(x, y)
|
||||
Dim As Long l = Len(di) -1
|
||||
If l < 0 Then Exit Sub ' no directions left then exit
|
||||
di_n = di[l] ' get direction
|
||||
If l = 0 Then
|
||||
d(x,y) = ""
|
||||
Else
|
||||
d(x,y) = Left(di,l)
|
||||
End If
|
||||
|
||||
Select Case di_n ' 0,0 is upper left corner
|
||||
Case Asc("N")
|
||||
x1 = x : y1 = y -1
|
||||
Case Asc("E")
|
||||
x1 = x +1 : y1 = y
|
||||
Case Asc("S")
|
||||
x1 = x : y1 = y +1
|
||||
Case Asc("W")
|
||||
x1 = x -1 : y1 = y
|
||||
End Select
|
||||
|
||||
If c(x1,y1) <> 0 Then Continue Do
|
||||
|
||||
Select Case di_n ' 0,0 is upper left corner
|
||||
Case Asc("N")
|
||||
Line (x * s +1 , y * s) - ((x +1) * s -1, y * s),0
|
||||
Case Asc("E")
|
||||
Line (x1 * s, y * s +1) - (x1 * s, (y +1) * s -1),0
|
||||
Case Asc("S")
|
||||
Line (x * s +1, y1 * s) - ((x +1) * s -1, y1 * s),0
|
||||
Case Asc("W")
|
||||
Line (x * s , y * s +1) - (x * s, (y +1) * s -1),0
|
||||
End Select
|
||||
|
||||
cell(x1, y1, s)
|
||||
Loop
|
||||
|
||||
End Sub
|
||||
|
||||
Sub gen_maze(w As ULong, h As ULong, s As ULong)
|
||||
|
||||
ReDim d(w, h)
|
||||
ReDim c(w, h)
|
||||
Dim As ULong x, y, r, i
|
||||
Dim As String di
|
||||
|
||||
d(0, 0) = "SE" ' cornes
|
||||
d(0, h -1) ="NE"
|
||||
d(w -1, 0) ="SW"
|
||||
d(w -1, h -1) ="NW"
|
||||
|
||||
For x = 1 To w -2 ' sides
|
||||
d(x,0) = "EWS"
|
||||
d(x,h -1) = "NEW"
|
||||
Next
|
||||
|
||||
For y = 1 To h -2
|
||||
d(0, y) = "NSE"
|
||||
d(w -1, y) ="NSW"
|
||||
Next
|
||||
|
||||
For x = 0 To w -1 ' shuffle directions
|
||||
For y = 0 To h -1
|
||||
di = d(x,y)
|
||||
If di = "" Then di = "NEWS"
|
||||
i = Len(di)
|
||||
Do
|
||||
r = Fix(Rnd * i)
|
||||
i = i - 1
|
||||
Swap di[r], di[i]
|
||||
Loop Until i = 0
|
||||
d(x,y) = di
|
||||
Next
|
||||
Next
|
||||
|
||||
ScreenRes w * s +1, h * s +1, 8
|
||||
' draw the grid
|
||||
For x = 0 To w
|
||||
Line (x * s, 0) - (x * s, h * s), 2 ' green color
|
||||
Next
|
||||
|
||||
For y = 0 To h
|
||||
Line(0, y * s) - (w* s, y * s),2
|
||||
Next
|
||||
' choice the start cell
|
||||
x = Fix(Rnd * w)
|
||||
y = Fix(Rnd * h)
|
||||
|
||||
cell(x, y, s)
|
||||
|
||||
End Sub
|
||||
|
||||
' ------=< MAIN >=------
|
||||
|
||||
Randomize Timer
|
||||
|
||||
Dim As ULong t
|
||||
|
||||
Do
|
||||
' gen_maxe(width, height, cell size)
|
||||
gen_maze(30, 30, 20)
|
||||
WindowTitle " S to save, N for next maze, other key to stop"
|
||||
Do
|
||||
Var key = Inkey
|
||||
key = UCase(key)
|
||||
If key = "S" Then
|
||||
t = t +1
|
||||
BSave("maze" + Str(t) + ".bmp"), 0
|
||||
key = ""
|
||||
End If
|
||||
If key = "N" Then Continue Do, Do
|
||||
If key <> "" Then Exit Do, Do
|
||||
Loop
|
||||
Loop
|
||||
|
||||
End
|
||||
37
Task/Maze-generation/Nim/maze-generation.nim
Normal file
37
Task/Maze-generation/Nim/maze-generation.nim
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import math, sequtils, strutils
|
||||
randomize()
|
||||
|
||||
template newSeqWith(len: int, init: expr): expr =
|
||||
var result {.gensym.} = newSeq[type(init)](len)
|
||||
for i in 0 .. <len:
|
||||
result[i] = init
|
||||
result
|
||||
|
||||
iterator randomCover[T](xs: openarray[T]): T =
|
||||
var js = toSeq 0..xs.high
|
||||
for i in countdown(js.high, 0):
|
||||
let j = random(i + 1)
|
||||
swap(js[i], js[j])
|
||||
for j in js:
|
||||
yield xs[j]
|
||||
|
||||
const
|
||||
w = 14
|
||||
h = 10
|
||||
|
||||
var
|
||||
vis = newSeqWith(h, newSeq[bool](w))
|
||||
hor = newSeqWith(h+1, newSeqWith(w, "+---"))
|
||||
ver = newSeqWith(h, newSeqWith(w, "| ") & "|")
|
||||
|
||||
proc walk(x, y) =
|
||||
vis[y][x] = true
|
||||
for p in [[x-1,y], [x,y+1], [x+1,y], [x,y-1]].randomCover:
|
||||
if p[0] notin 0 .. <w or p[1] notin 0 .. <h or vis[p[1]][p[0]]: continue
|
||||
if p[0] == x: hor[max(y, p[1])][x] = "+ "
|
||||
if p[1] == y: ver[y][max(x, p[0])] = " "
|
||||
walk p[0], p[1]
|
||||
|
||||
walk random(0..w), random(0..h)
|
||||
for a,b in zip(hor, ver & @[""]).items:
|
||||
echo join(a & "+\n" & b)
|
||||
33
Task/Maze-generation/Sidef/maze-generation.sidef
Normal file
33
Task/Maze-generation/Sidef/maze-generation.sidef
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
var(w:5, h:5) = ARGV.map{.to_i}...
|
||||
var avail = (w * h)
|
||||
|
||||
# cell is padded by sentinel col and row, so I don't check array bounds
|
||||
var cell = (1..h -> map {([true] * w) + [false]} + [[false] * w+1])
|
||||
var ver = (1..h -> map {["| "] * w })
|
||||
var hor = (0..h -> map {["+--"] * w })
|
||||
|
||||
func walk(x, y) {
|
||||
cell[y][x] = false;
|
||||
avail-- > 0 || return; # no more bottles, er, cells
|
||||
|
||||
var d = [[-1, 0], [0, 1], [1, 0], [0, -1]]
|
||||
while (!d.is_empty) {
|
||||
var i = d.pop_rand
|
||||
var (x1, y1) = (x + i[0], y + i[1])
|
||||
|
||||
cell[y1][x1] || next
|
||||
|
||||
if (x == x1) { hor[[y1, y].max][x] = '+ ' }
|
||||
if (y == y1) { ver[y][[x1, x].max] = ' ' }
|
||||
walk(x1, y1)
|
||||
}
|
||||
}
|
||||
|
||||
walk(w.rand.int, h.rand.int) # generate
|
||||
|
||||
for i in (0 .. h) {
|
||||
say (hor[i].join('') + '+')
|
||||
if (i < h) {
|
||||
say (ver[i].join('') + '|')
|
||||
}
|
||||
}
|
||||
109
Task/Maze-generation/Swift/maze-generation.swift
Normal file
109
Task/Maze-generation/Swift/maze-generation.swift
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import Foundation
|
||||
|
||||
class Direction {
|
||||
var vect:(Int, Int, Int)
|
||||
var bit:Int {
|
||||
let (bit, dx, dy) = vect
|
||||
return bit
|
||||
}
|
||||
|
||||
var dx:Int {
|
||||
let (bit, dx, dy) = vect
|
||||
return dx
|
||||
}
|
||||
|
||||
var dy:Int {
|
||||
let (bit, dx, dy) = vect
|
||||
return dy
|
||||
}
|
||||
|
||||
var opposite:Direction {
|
||||
switch (vect) {
|
||||
case (1, 0, -1):
|
||||
return Direction(bit: 2, dx: 0, dy: 1)
|
||||
case (2, 0, 1):
|
||||
return Direction(bit: 1, dx: 0, dy: -1)
|
||||
case (4, 1, 0):
|
||||
return Direction(bit: 8, dx: -1, dy: 0)
|
||||
case (8, -1, 0):
|
||||
return Direction(bit: 4, dx: 1, dy: 0)
|
||||
default:
|
||||
return Direction(bit: 0, dx: 0, dy: 0)
|
||||
}
|
||||
}
|
||||
|
||||
init(bit:Int, dx:Int, dy:Int) {
|
||||
self.vect = (bit, dx, dy)
|
||||
}
|
||||
}
|
||||
|
||||
let N = Direction(bit: 1, dx: 0, dy: -1)
|
||||
let S = Direction(bit: 2, dx: 0, dy: 1)
|
||||
let E = Direction(bit: 4, dx: 1, dy: 0)
|
||||
let W = Direction(bit: 8, dx: -1, dy: 0)
|
||||
|
||||
class MazeGenerator {
|
||||
let x:Int!
|
||||
let y:Int!
|
||||
var maze:[[Int]]!
|
||||
|
||||
init(_ x:Int, _ y:Int) {
|
||||
self.x = x
|
||||
self.y = y
|
||||
var col = [Int](count: y, repeatedValue: 0)
|
||||
self.maze = [[Int]](count: x, repeatedValue: col)
|
||||
generateMaze(0, 0)
|
||||
}
|
||||
|
||||
func display() {
|
||||
for i in 0..<y {
|
||||
// Draw top edge
|
||||
for j in 0..<x {
|
||||
print((maze[j][i] & 1) == 0 ? "+---" : "+ ")
|
||||
}
|
||||
println("+")
|
||||
|
||||
// Draw left edge
|
||||
for j in 0..<x {
|
||||
print((maze[j][i] & 8) == 0 ? "| " : " ")
|
||||
}
|
||||
println("|")
|
||||
}
|
||||
|
||||
// Draw bottom edge
|
||||
for j in 0..<x {
|
||||
print("+---")
|
||||
}
|
||||
println("+")
|
||||
}
|
||||
|
||||
func generateMaze(cx:Int, _ cy:Int) {
|
||||
var dirs = [N, S, E, W] as NSMutableArray
|
||||
for i in 0..<dirs.count {
|
||||
let x1 = Int(arc4random()) % dirs.count
|
||||
let x2 = Int(arc4random()) % dirs.count
|
||||
dirs.exchangeObjectAtIndex(x1, withObjectAtIndex: x2)
|
||||
}
|
||||
|
||||
for dir in dirs {
|
||||
var dir = dir as Direction
|
||||
let nx = cx + dir.dx
|
||||
let ny = cy + dir.dy
|
||||
if (between(nx, self.x) && between(ny, self.y) && (maze[nx][ny] == 0)) {
|
||||
maze[cx][cy] |= dir.bit
|
||||
maze[nx][ny] |= dir.opposite.bit
|
||||
generateMaze(nx, ny)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func between(v:Int, _ upper:Int) -> Bool {
|
||||
return (v >= 0) && (v < upper)
|
||||
}
|
||||
}
|
||||
|
||||
let x = 10
|
||||
let y = 10
|
||||
let maze = MazeGenerator(x, y)
|
||||
maze.display()
|
||||
Loading…
Add table
Add a link
Reference in a new issue