From 9572876457d55f19f212a3024f70fce7bcec2828 Mon Sep 17 00:00:00 2001 From: Gregory Date: Sat, 10 Oct 2020 12:53:23 +0300 Subject: [PATCH] init --- .gitignore | 3 ++ 01/Fuel.fs | 115 +++++++++++++++++++++++++++++++++++++++++++++ 01/Fuel.fsproj | 12 +++++ 02/Opcode.fs | 45 ++++++++++++++++++ 02/Opcode.fsproj | 12 +++++ 03/Distance.fs | 81 +++++++++++++++++++++++++++++++ 03/Distance.fsproj | 12 +++++ 04/Pass.fs | 57 ++++++++++++++++++++++ 04/Pass.fsproj | 12 +++++ 05/Test.fs | 81 +++++++++++++++++++++++++++++++ 05/Test.fsproj | 12 +++++ 11 files changed, 442 insertions(+) create mode 100644 .gitignore create mode 100644 01/Fuel.fs create mode 100644 01/Fuel.fsproj create mode 100644 02/Opcode.fs create mode 100644 02/Opcode.fsproj create mode 100644 03/Distance.fs create mode 100644 03/Distance.fsproj create mode 100644 04/Pass.fs create mode 100644 04/Pass.fsproj create mode 100644 05/Test.fs create mode 100644 05/Test.fsproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c120255 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/*/bin +/*/obj +/*/.ionide diff --git a/01/Fuel.fs b/01/Fuel.fs new file mode 100644 index 0000000..9af6751 --- /dev/null +++ b/01/Fuel.fs @@ -0,0 +1,115 @@ +let moduleMasses = """79620 +58052 +119910 +138477 +139102 +78373 +51937 +63751 +100937 +56664 +128939 +115929 +136981 +68215 +90317 +97455 +130858 +94009 +123221 +81390 +61726 +78271 +73354 +103061 +131261 +140510 +120555 +117319 +91154 +96009 +75491 +90245 +141689 +118783 +104601 +121969 +98547 +108924 +117114 +65916 +120037 +66166 +93973 +105777 +63501 +89199 +117551 +126021 +93466 +107901 +82323 +104471 +98794 +57270 +59457 +120558 +128142 +137648 +127375 +103353 +116578 +97950 +110725 +96438 +128425 +75503 +132178 +138363 +67009 +127873 +135747 +108109 +118818 +75396 +92822 +63886 +82973 +116243 +129066 +74185 +145298 +83483 +83417 +54682 +55648 +142206 +121420 +149890 +56561 +107108 +111376 +139885 +147373 +131657 +140634 +79704 +90263 +139892 +103841 +50730""" + +let totalFuel (masses: string) = + + let calcFuel (mass: float) = + (System.Math.Floor (mass / 3.)) - 2. + + masses.Split [|'\n'|] + |> List.ofArray + |> List.map (float >> calcFuel) + |> List.reduce (+) + +[] +let main (_: string[]) = + printf "total fuel: %f" (totalFuel "100756") + 0 \ No newline at end of file diff --git a/01/Fuel.fsproj b/01/Fuel.fsproj new file mode 100644 index 0000000..e7d625a --- /dev/null +++ b/01/Fuel.fsproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.0 + Exe + + + + + + + diff --git a/02/Opcode.fs b/02/Opcode.fs new file mode 100644 index 0000000..272d9b1 --- /dev/null +++ b/02/Opcode.fs @@ -0,0 +1,45 @@ +let programCode = "1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,9,19,1,10,19,23,2,9,23,27,1,6,27,31,2,31,9,35,1,5,35,39,1,10,39,43,1,10,43,47,2,13,47,51,1,10,51,55,2,55,10,59,1,9,59,63,2,6,63,67,1,5,67,71,1,71,5,75,1,5,75,79,2,79,13,83,1,83,5,87,2,6,87,91,1,5,91,95,1,95,9,99,1,99,6,103,1,103,13,107,1,107,5,111,2,111,13,115,1,115,6,119,1,6,119,123,2,123,13,127,1,10,127,131,1,131,2,135,1,135,5,0,99,2,14,0,0" + + +let translate (programCode: string) = + + let restore (codes: int array) = + codes.[1] <- 12 + codes.[2] <- 2 + codes + + programCode.Split [| ',' |] + |> Array.map int + |> restore + +let write reg1 reg2 reg3 (memory: int array) f = + memory.[reg3] <- f memory.[reg1] memory.[reg2] + memory + +let eval opcode = + match opcode with + | 1 -> Some (+) + | 2 -> Some (*) + | _ -> None + +let rec run (program: int array) (memory: int array) = + + let opCode = program.[0] + let reg1 = program.[1] + let reg2 = program.[2] + let reg3 = program.[3] + + match eval opCode with + | Some op -> run program.[4 .. ] (write reg1 reg2 reg3 memory op) + | _ -> memory + +[] +let main (_: string[]) = + + let program = translate programCode + + let result = run program program + + printf "%d" result.[0] + + 0 \ No newline at end of file diff --git a/02/Opcode.fsproj b/02/Opcode.fsproj new file mode 100644 index 0000000..b9ae09f --- /dev/null +++ b/02/Opcode.fsproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.0 + Exe + + + + + + + diff --git a/03/Distance.fs b/03/Distance.fs new file mode 100644 index 0000000..f90cb46 --- /dev/null +++ b/03/Distance.fs @@ -0,0 +1,81 @@ +type Point = (int * int) + +let path1 = """R999,D467,L84,D619,L49,U380,R287,U80,R744,D642,L340,U738,R959,U710,R882,U861,L130,D354,L579,D586,R798,D735,L661,D453,L828,U953,R604,D834,R921,D348,R620,U775,R364,U552,L221,U119,R590,U29,L267,D745,L128,U468,L978,D717,R883,D227,R691,D330,L33,U520,L862,D132,R99,U400,L455,U737,L603,U220,L689,U131,R158,D674,R617,D287,R422,U734,L73,U327,L525,D245,R849,D692,R114,U136,R762,D5,R329,U429,L849,U748,R816,U556,R614,D412,R416,D306,R307,U826,R880,U936,L164,U984,L689,D934,R790,D14,R561,D736,L3,D442,R301,D520,L451,U76,R844,D307,L144,D800,L462,D138,R956,U225,L393,D186,L924,D445,L86,D640,L920,D877,L197,U191,L371,D701,R826,D282,R856,D412,L788,D417,R69,D678,R978,D268,L268,U112,L69,U164,L748,U191,R227,D227,R59,U749,R134,U779,R865,U247,R55,D567,R821,U799,R937,D942,L445,D571,R685,D111,R107,D769,R269,D968,R102,U335,R538,U125,L725,D654,R451,D242,R777,U813,R799,D786,L804,U313,L322,U771,R219,U316,L973,U963,R84,D289,R825,D299,L425,D49,R995,D486,R550,D789,R735,D501,R966,U955,R432,U635,L353,D600,R675,D236,R864,U322,R719,D418,L877,U833,R839,D634,L533,D438,L734,U130,L578,U498,L984,D413,L615,U40,L699,U656,L653,U419,R856,U882,R30,D266,R386,D692,L210,U802,L390,U753,L406,U338,R743,D320,L125,U204,R391,U537,R887,D194,L302,U400,R510,U92,L310,D382,R597,U498,R851,D357,L568,U800,R918,D106,R673,D735,L86,D67,R398,D677,R355,D501,L909,D133,R729,D293,L498,U222,R832,U671,R751,U36,R422,U840,L636,D476,L292,D105,L239,U199,R669,U736,L345,D911,L277,U452,L979,D153,R882,U604,R602,U495,L311,U453,L215,D713,R873""" + +// let path1 = "R8,U5,L5,D3" + +let path2 = """L996,U773,L865,D472,L988,D570,L388,U458,L87,U885,L115,U55,R75,U582,R695,U883,R83,U285,R96,D244,L647,D359,R136,U107,R912,U871,L844,U395,L63,U899,L205,D137,R549,U221,L859,D429,L809,U127,R304,U679,L511,U144,R926,U95,L805,U811,R42,D248,L546,D644,L551,D897,R368,D391,L224,U164,L490,D991,L146,D615,R536,U247,R10,U998,L957,D233,R706,D926,R760,U438,R270,D983,R134,U738,L262,U301,L480,D635,L702,D715,R479,U500,R19,D291,R368,U203,R305,D999,R106,U355,L683,D298,R90,U968,L254,D936,R89,U496,R253,U688,R99,U637,L783,D451,R673,D762,R997,D50,L488,U551,L871,U388,R949,D371,R584,D908,L880,U523,R557,U436,R520,U587,L56,U18,R397,U541,R660,D444,R51,U187,R221,U902,R726,U303,R97,D817,R185,D218,L240,D67,L259,U334,R821,U629,R21,D970,R282,U155,R555,D678,L99,D570,R863,D405,R941,U584,L303,D109,L871,U180,R595,D226,L670,D943,L127,U647,R452,D570,R75,D284,R414,U404,R515,U993,R408,U488,R890,D318,L415,U969,R769,D976,L732,U1,R489,U655,R930,U638,R649,D254,R161,U287,L659,D26,L477,D821,L124,U538,R17,D711,L203,U888,R904,U648,L908,D65,L215,U283,R698,U28,R72,U214,R499,D89,R489,D58,R949,D91,L710,U960,L755,D402,L27,D873,R61,U607,R57,D548,R369,U622,L244,U19,R61,D606,R928,D968,R10,D988,R816,U500,R915,D400,R546,D283,L627,D919,L259,U337,R374,U795,L355,D989,L224,D77,L872,U901,R476,U765,L320,U768,L937,D437,R141,D822,L326,D324,L498,U994,L518,D857,R973,D681,L710,D590,L879,U499,R488,D151,L242,U988,L944,U683,L24,U491,R823,D246,R872,D654,R28,U581,L142,U31,R435,D686,L147,D102,R952,D607,L959,D929,L46""" + +// let path2 = "U7,R6,D4,L4" + +let toPoints (path: string): Point list = + + let pointFromString (direction: string) = + + let distance = int (direction.Substring 1) + + match direction.[0] with + | 'L' -> (-distance, 0) + | 'R' -> (distance, 0) + | 'D' -> (0, -distance) + | 'U' -> (0, distance) + | _ -> (0, 0) + + + let addPoints (x1, y1) (x2, y2) = + (x1 + x2, y1 + y2) + + let step points direction = + + let nextPoint = + addPoints (pointFromString direction) (Array.last points) + + Array.append points [| nextPoint |] + + path.Split [| ',' |] |> Array.fold step [| Point (0 , 0) |] |> List.ofArray + + +let rec foldPoints folder state points = + match points with + | a :: b :: tail -> foldPoints folder (folder state (a, b)) (b :: tail) + | _ -> state + +let manhattanDistance (a, b) (c, d) = + abs (a - c) + abs (b - d) + +let printPoints points = List.iter (printfn "%A") points + +let linesIntersect (((_, ay), (bx, by)) as a) (((cx, cy), (dx, _)) as b) = + let firstPart = (by - cy) * (cy - ay) + let secondPart = (cx - bx) * (bx - dx) + if firstPart > 0 && secondPart > 0 + then (bx, cy) + else (0, 0) + +[] +let main (_: string array) = + let points1 = toPoints path1 + let points2 = toPoints path2 + (foldPoints + (fun intersections1 (((ax, _), (bx, _)) as line1) -> + let line1isVertical = ax = bx + intersections1 @ (foldPoints + (fun intersections2 (((cx, _), (dx, _)) as line2) -> + let line2isVertical = cx = dx + match (line1isVertical, line2isVertical) with + | (true, true) | (false, false) -> intersections2 + | (true, false) -> (linesIntersect line1 line2) :: intersections2 + | (false, true) -> (linesIntersect line2 line1) :: intersections2 + ) + [] + points2) + ) + [] + points1) + |> List.filter (fun (a, b) -> not (a = 0 && b = 0)) + |> List.fold (fun distances intersection -> (manhattanDistance (0, 0) intersection) :: distances) [] + |> List.sort + |> List.rev + |> List.iter (printfn "%d") + + 0 \ No newline at end of file diff --git a/03/Distance.fsproj b/03/Distance.fsproj new file mode 100644 index 0000000..3f7e57b --- /dev/null +++ b/03/Distance.fsproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.0 + Exe + + + + + + + diff --git a/04/Pass.fs b/04/Pass.fs new file mode 100644 index 0000000..efd85eb --- /dev/null +++ b/04/Pass.fs @@ -0,0 +1,57 @@ +let split (str: string) = Array.toList (str.ToCharArray ()) + +let isIncreasing (password: int) = + + let isBiggerOrSame (prev, isTrue) current = + (current, isTrue && prev <= current) + + string password + |> split + |> List.map int + |> List.fold isBiggerOrSame (0, true) + |> snd + +let hasPair (password: int) = + + let rec find adjasent pass = + match pass with + | [] -> adjasent + | a :: b :: _ when a = b -> true + | _ :: tail -> find adjasent tail + + string password + |> split + |> find false + +let hasOnlyEvenRepeatings (password: int) = + + let rec find adjasent (pass: char list) = + match pass with + | [] -> adjasent + | a :: b :: c :: d :: e :: f :: g :: _ when a = b && b = c && c = d && d = e && e = f && f = g -> true + | a :: b :: c :: d :: e :: f :: _ when a = b && b = c && c = d && d = e && e <> f -> false + | a :: b :: c :: d :: e :: _ when a = b && b = c && c = d && d <> e -> true + | a :: b :: c :: d :: _ when a = b && b = c && c <> d -> false + | a :: b :: c :: _ when a = b && b <> c -> true + | _ :: tail -> find adjasent tail + + string password + |> split + |> find true + +let passConditions pass = + + let apply f (pass, passes) = (pass, passes && f pass) + + (pass, true) + |> apply hasPair + |> apply isIncreasing + |> apply hasOnlyEvenRepeatings + |> snd + + +[] +let main _ = + printfn + "%d" ([172930 .. 683082] |> List.filter passConditions |> List.length) + 0 \ No newline at end of file diff --git a/04/Pass.fsproj b/04/Pass.fsproj new file mode 100644 index 0000000..d88f7d5 --- /dev/null +++ b/04/Pass.fsproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.0 + Exe + + + + + + + diff --git a/05/Test.fs b/05/Test.fs new file mode 100644 index 0000000..e0d9ca0 --- /dev/null +++ b/05/Test.fs @@ -0,0 +1,81 @@ + +type Memory = string array + +type Instruction = int + +type Modes = (int * int * int) + +type State = (Memory * Instruction) + +type Operation = (State * Modes) -> State + + +let program = "3,225,1,225,6,6,1100,1,238,225,104,0,1102,88,66,225,101,8,125,224,101,-88,224,224,4,224,1002,223,8,223,101,2,224,224,1,224,223,223,1101,87,23,225,1102,17,10,224,101,-170,224,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,1101,9,65,225,1101,57,74,225,1101,66,73,225,1101,22,37,224,101,-59,224,224,4,224,102,8,223,223,1001,224,1,224,1,223,224,223,1102,79,64,225,1001,130,82,224,101,-113,224,224,4,224,102,8,223,223,1001,224,7,224,1,223,224,223,1102,80,17,225,1101,32,31,225,1,65,40,224,1001,224,-32,224,4,224,102,8,223,223,1001,224,4,224,1,224,223,223,2,99,69,224,1001,224,-4503,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1002,14,92,224,1001,224,-6072,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,102,33,74,224,1001,224,-2409,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,107,677,677,224,1002,223,2,223,1006,224,329,101,1,223,223,108,677,677,224,1002,223,2,223,1005,224,344,101,1,223,223,1007,677,677,224,1002,223,2,223,1006,224,359,101,1,223,223,1107,226,677,224,1002,223,2,223,1006,224,374,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,389,101,1,223,223,1108,677,677,224,1002,223,2,223,1005,224,404,1001,223,1,223,7,226,226,224,1002,223,2,223,1006,224,419,101,1,223,223,1107,677,677,224,1002,223,2,223,1005,224,434,101,1,223,223,107,226,226,224,102,2,223,223,1005,224,449,101,1,223,223,107,677,226,224,1002,223,2,223,1006,224,464,1001,223,1,223,8,226,677,224,102,2,223,223,1006,224,479,1001,223,1,223,108,677,226,224,102,2,223,223,1005,224,494,1001,223,1,223,1108,677,226,224,1002,223,2,223,1005,224,509,1001,223,1,223,1107,677,226,224,1002,223,2,223,1005,224,524,101,1,223,223,1008,226,226,224,1002,223,2,223,1006,224,539,101,1,223,223,1008,226,677,224,1002,223,2,223,1005,224,554,1001,223,1,223,7,226,677,224,1002,223,2,223,1005,224,569,101,1,223,223,1007,677,226,224,1002,223,2,223,1006,224,584,1001,223,1,223,7,677,226,224,102,2,223,223,1006,224,599,101,1,223,223,1007,226,226,224,102,2,223,223,1006,224,614,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,629,101,1,223,223,108,226,226,224,102,2,223,223,1006,224,644,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,659,101,1,223,223,8,226,226,224,1002,223,2,223,1005,224,674,101,1,223,223,4,223,99,226" +// let program = "1002,4,3,4,33".Split [| ',' |] + +let dereference (mem: Memory) pointer mode = + let value = mem.[pointer] + if mode = 1 + then value + else mem.[int value] + +let add ((mem, ip): State) ((m1, m2, _): Modes): State = + + let op1 = dereference mem (ip + 1) m1 + let op2 = dereference mem (ip + 2) m2 + let addr = dereference mem (ip + 3) 1 + + mem.[int addr] <- string ((int op1) + (int op2)) + + (mem, ip + 4) + +let mul ((mem, ip): State) ((m1, m2, _): Modes): State = + + let op1 = dereference mem (ip + 1) m1 + let op2 = dereference mem (ip + 2) m2 + let addr = dereference mem (ip + 3) 1 + + mem.[int addr] <- string ((int op1) * (int op2)) + + (mem, ip + 4) + +let inp ((mem, ip): State) (_): State = + let address = dereference mem (ip + 1) 1 + printf "input: " + mem.[int address] <- System.Console.ReadLine () + (mem, ip + 2) + +let out ((mem, ip): State) (_): State = + let address = dereference mem (ip + 1) 1 + printfn "%s" mem.[int address] + (mem, ip + 2) + +let getModes (opcode: string array) length: Modes = + + let toMode index = + Array.tryItem (length - index) opcode |> Option.defaultValue "0" |> int + + (toMode 3, toMode 4, toMode 5) + +let eval ((mem, ip) as state: State): State option = + + let opcode = mem.[ip].ToCharArray () |> Array.map string + let modes = getModes opcode opcode.Length + let code = Array.last opcode |> int + + match code with + | 1 -> Some (add state modes) + | 2 -> Some (mul state modes) + | 3 -> Some (inp state modes) + | 4 -> Some (out state modes) + | _ -> None + +let rec run (state: State): State = + match eval state with + | Some newState -> run newState + | None -> state + +[] +let main (_: string[]) = + run (program.Split [| ',' |], 0) |> ignore + 0 \ No newline at end of file diff --git a/05/Test.fsproj b/05/Test.fsproj new file mode 100644 index 0000000..33b1931 --- /dev/null +++ b/05/Test.fsproj @@ -0,0 +1,12 @@ + + + + netcoreapp3.0 + Exe + + + + + + +