├── LICENSE ├── README.md ├── aoc ├── 2021 │ ├── 01-sonar-sweep.md │ ├── 02-dive.md │ ├── 03-binary-diagnostic.md │ ├── 04-giant-squid.md │ ├── 05-hydrothermal-venture.md │ ├── 06-lanternfish.md │ ├── 07-treachery-of-whales.md │ ├── 08-seven-segment-search.md │ ├── 09-smoke-basin.md │ ├── 10-syntax-scoring.md │ ├── 11-dumbo-octopus.md │ ├── 12-passage-pathing.md │ ├── 13-transparent-origami.md │ ├── 14-extended-polymerization.md │ ├── README.md │ ├── img │ │ ├── lanternfish.jpg │ │ └── vents.jpg │ ├── input │ │ ├── 01.txt │ │ ├── 02.txt │ │ ├── 03.txt │ │ ├── 04.txt │ │ ├── 05.txt │ │ ├── 06.txt │ │ ├── 07.txt │ │ ├── 08.txt │ │ ├── 09.txt │ │ ├── 10.txt │ │ ├── 11.txt │ │ ├── 12.txt │ │ ├── 13.txt │ │ └── 14.txt │ └── test │ │ ├── 01.txt │ │ ├── 02.txt │ │ ├── 03.txt │ │ ├── 04.txt │ │ ├── 05.txt │ │ ├── 06.txt │ │ ├── 07.txt │ │ ├── 08.txt │ │ ├── 09.txt │ │ ├── 10.txt │ │ ├── 11.txt │ │ ├── 12.txt │ │ ├── 13.txt │ │ ├── 14.txt │ │ └── 15.txt └── 2022 │ ├── 01.md │ ├── 02.md │ ├── 03.md │ ├── 04.md │ ├── 05.md │ ├── 06.md │ ├── 07.md │ ├── 08.md │ ├── 09.md │ ├── 10.md │ ├── 11.md │ ├── 12.md │ ├── 13.md │ ├── 14.md │ ├── 15.md │ ├── 16.md │ ├── 17.gif │ ├── 17.md │ ├── 18.md │ ├── README.md │ ├── img │ └── crates.gif │ ├── input │ ├── 01.txt │ ├── 02.txt │ ├── 03.txt │ ├── 04.txt │ ├── 05.txt │ ├── 06.txt │ ├── 07.txt │ ├── 08.txt │ ├── 09.txt │ ├── 10.txt │ ├── 11.txt │ ├── 12.txt │ ├── 13.txt │ ├── 14.txt │ ├── 15.txt │ ├── 16.txt │ ├── 17.txt │ ├── 18.txt │ ├── 19.txt │ ├── 20.txt │ ├── 21.txt │ ├── 22.txt │ ├── 23.txt │ ├── 24.txt │ └── 25.txt │ ├── q │ ├── 01.q │ ├── 02.q │ ├── 03.q │ ├── 04.q │ ├── 05.q │ ├── 06.q │ ├── 07.q │ ├── 08.q │ ├── 09.q │ ├── 10.q │ ├── 11.q │ ├── 12.q │ ├── 13.q │ ├── 14.q │ ├── 15.q │ ├── 16.q │ ├── 17.q │ ├── 18.q │ ├── 19.c │ ├── 19.q │ ├── 20.q │ ├── 21.q │ ├── 22.q │ ├── 23.q │ ├── 24.q │ └── 25.q │ └── test │ ├── 01.txt │ ├── 02.txt │ ├── 03.txt │ ├── 04.txt │ ├── 05.txt │ ├── 06.txt │ ├── 07.txt │ ├── 08.txt │ ├── 09.txt │ ├── 10.txt │ ├── 11.txt │ ├── 12.txt │ ├── 13.txt │ ├── 14.txt │ ├── 15.txt │ ├── 16.txt │ ├── 17.txt │ ├── 18.txt │ ├── 19.txt │ ├── 20.txt │ ├── 21.txt │ ├── 22.txt │ ├── 23.txt │ ├── 24.txt │ └── 25.txt ├── essays ├── allthatjazz.md ├── findingprimes.md ├── img │ ├── classic-jazz.jpg │ ├── lightbulb-wide.png │ ├── mp3s-after.png │ ├── mp3s-before.png │ ├── playlist.png │ └── prime-numbers.jpg └── zenmonks.md ├── euler ├── 01.md ├── 02.md ├── 03.md ├── 03.q ├── 04.md ├── 04.q ├── 05.md ├── 05.q ├── 06.md ├── 06.q ├── 07.md ├── 07.q ├── 07a.q ├── 08.q ├── 08.txt ├── 09.md ├── 11.q ├── 11.txt ├── 800px-PrimitivePythagoreanTriplesRev08.svg.png └── Sieve_of_Eratosthenes_animation.gif ├── games ├── boggle.md ├── fizzbuzz.md ├── img │ ├── boggle.jpg │ ├── fizzbuzz.png │ ├── klondike.png │ └── scrabble.jpg ├── klondike.md ├── klondike.q └── scrabble.md ├── leetcode ├── 53.md ├── 53.q ├── 976.md └── 976.q ├── puzzles ├── 100prisoners.md ├── img │ └── cats-cradle.jpg ├── run-length-encoding.md └── strings.md ├── resources.md └── rosetta ├── abc-problem.md ├── abundant-odds.md ├── four-magic.md ├── img ├── 2ADY7DK.jpg ├── 2C9PF21.jpg ├── CN6580.jpg ├── G36AKX.jpg ├── PHPHX0.jpg ├── WJEGGB.jpg └── name-game.png ├── name-game.md ├── sum-say.md ├── word-wheel.md ├── ww.q └── xmas-days.md /README.md: -------------------------------------------------------------------------------- 1 | ![Maintenance](https://img.shields.io/maintenance/yes/2023?style=for-the-badge) 2 | 3 | Study Q 4 | ======= 5 | 6 | *Tutorials, puzzles, exercises, essays and other study resources for the q programming language* 7 | 8 | Most users of q encounter it as a means of querying large kdb+ datasets. 9 | But it is also a general-purpose programming language (PL) of great power and expressiveness, 10 | and a direct descendant of both APL and Lisp, 11 | early PLs that stamped their influence on the many languages that followed them. 12 | 13 | If you find the verbosity of ‘high ceremony’ languages comforting, you will not like q. 14 | But if you like coding at a high level of abstraction and also in **sympathy with the metal** 15 | (q’s Unique Selling Point is its speed) you may find its terse expressions utterly addictive. 16 | 17 | Long experience with ‘scalar’ languages train the brain to break problems into loops. 18 | Most q operators iterate *implicitly* 19 | ```q 20 | q)1 2 3 + 4 21 | 5 6 7 22 | ``` 23 | so novice q programmers (qbies) have a certain amount of *unlearning* to do. 24 | You may experience this as a cognitive *decluttering* that frees you up to focus on algorithms and strategies. 25 | 26 | 27 | Gods and mortals 28 | ---------------- 29 | Prior experience with its ancestor languages APL, k, and Lisp made q a familiar environment 30 | for many of its early adopters. Their need for training was minimal, 31 | and documentation little more than a memory aid. 32 | 33 | Marvelling at bafflingly terse q solutions, qbies dubbed early adopters “the q gods”. 34 | The expression honours their skill – but also places it out of reach. 35 | With grim humour, a popular textbook for the language took the title 36 | [*Q for Mortals*](https://code.kx.com/q4m3) 37 | – how the rest of us can scrape by when using the language of the gods: 38 | a traveller’s phrasebook for Coding Heaven. 39 | 40 | This repository is a [Promethean](https://en.wikipedia.org/wiki/Prometheus "Wikipedia") project. 41 | Like any other language, q yields to study and practice. 42 | It is not reserved to a race of divine creatures. 43 | 44 | Go for it. 45 | 46 | 47 | Vector thinking 48 | --------------- 49 | The q language was designed to make the power of kdb+ more accessible to new users. 50 | With a little study, a new q user with prior experience of SQL can quickly start working productively. 51 | 52 | But the real power of kdb+, and its **machine sympathy** comes with thinking and writing in vectors. How to learn this? 53 | 54 | Because of q’s origins in financial markets, most production q code is hidden by corporate networks and non-disclosure agreements. 55 | Outside these exclusive environments it can be hard to learn from experienced qbists. 56 | 57 | The code exhibited here offers valuable insight into how qbists work. 58 | 59 | It rewards study. 60 | 61 | 62 | Contribute 63 | ---------- 64 | Much content here first appeared at code.kx.com/learn. 65 | It is reproduced in the hope that experienced qbists will extend it. 66 | 67 | You are welcome to post solution code (e.g. to Project Euler problems) without comment or explanation, but we strongly prefer discussion, particularly exploration of alternatives. 68 | -------------------------------------------------------------------------------- /aoc/2021/01-sonar-sweep.md: -------------------------------------------------------------------------------- 1 | # Day 1: Sonar Sweep 2 | 3 | > You're minding your own business on a ship at sea when the overboard alarm goes off! You rush to see if you can help. Apparently, one of the Elves tripped and accidentally sent the sleigh keys flying into the ocean! 4 | 5 | Advent of Code 2021 [Day 1](https://adventofcode.com/2021/day/1) 6 | 7 | --- 8 | 9 | Every puzzle has the same first step: ingesting the data. 10 | We‘re proud of how easy it is to convert each day’s text file into a tractable q data structure. 11 | 12 | ```q 13 | q)show d:"J"$read0 `$":input/01.txt" 14 | 148 167 168 169 182 188 193 209 195 206 214 219 225 219 211 215 216 195 200 1.. 15 | ``` 16 | 17 | How many of these depth measurements are larger than the previous measurement? 18 | 19 | The [Each Prior](https://code.kx.com/q/ref/maps/#each-prior) iterator applied to the Greater Than operator `>` 20 | derives a function `>':` that tells us exactly that. 21 | We use it with a zero left argument for the first comparison. 22 | 23 | ```q 24 | q)0>':d 25 | 11111111011110011010111111010111111101100011111001101110110011100110111101110.. 26 | ``` 27 | 28 | We’re not interested in the first comparison, so we discard it and count the remaining hits. 29 | 30 | ```q 31 | q)sum 1_ 0>':d 32 | 1400i 33 | ``` 34 | 35 | Because we are not interested in the first comparison, the 0 could be any integer. 36 | Perhaps better to get rid of it entirely, and apply `>':` as a unary, using either bracket or prefix syntax. 37 | 38 | ```q 39 | q)sum 1_ >':[d] / bracket 40 | 1400i 41 | q)sum 1_ (>':)d / prefix 42 | 1400i 43 | ``` 44 | 45 | Without the 0 left argument to `>':`, q has its own rules for what to compare the first item of `d` to. 46 | We don’t care, but you can read about these [defaults](https://code.kx.com/q/ref/maps/#each-prior). 47 | 48 | We see above that the derived function >': is variadic: we can apply it as either a unary or a binary. Applying it as a unary means we could instead use the prior keyword. 49 | 50 | ```q 51 | q)sum 1 _ (>) prior d 52 | 1400i 53 | ``` 54 | 55 | That is better q style, and perhaps the coolest way to write the solution. 56 | 57 | Note the parens in `(>)`, which give it noun syntax. 58 | That is, the parser reads it as the left argument of `prior` rather than trying to apply it. 59 | With this as a model, part 2 looks simple. 60 | We want the 3-point moving sums of `d`, of which we shall ignore the first two. 61 | 62 | ```q 63 | q)a:()!"j"$() / answers 64 | q)a[`$"1-1"]:sum 1 _ (>) prior d 65 | q)a[`$"1-2"]:sum 1 _ (>) prior 2 _ 3 msum d 66 | q)show a 67 | 1-1| 1400 68 | 1-2| 1429 69 | ``` 70 | 71 | Oleg Finkelshteyn has a simpler (and faster) solution. 72 | 73 | ```q 74 | q)sum(3_d)>-3_d 75 | 1429i 76 | ``` 77 | 78 | On [community.kx.com](https://community.kx.com/t5/Advent-of-Code-2021/AOC-Day-1-Sonar-Sweep/td-p/11352) user jbetz34 explains: 79 | 80 | ```q 81 | L:149 163 165 160 179 184 186 199 207 210 / first 10 depths 82 | sum L[0 1 2] < sum L[1 2 3] / compare first 2 moving sums 83 | L[0] + sum L[1 2] < L[3] + sum L[1 2] / factor out repeated sums 84 | L[0] < L[3] / simplified comparison 85 | ``` 86 | -------------------------------------------------------------------------------- /aoc/2021/02-dive.md: -------------------------------------------------------------------------------- 1 | # Day 2: Dive! 2 | 3 | > Now, you need to figure out how to pilot this thing. 4 | > 5 | > It seems like the submarine can take a series of commands like forward 1, down 2, or up 3… 6 | 7 | Advent of Code 2021 [Day 2](https://adventofcode.com/2021/day/2) 8 | 9 | --- 10 | 11 | Today‘s problem solution uses projections to ingest the data, then a table to think through a solution to the second part. Finally we reduce the table solution to a simpler vector expression. 12 | 13 | The text file consists of course adjustments that affect horizontal position and depth. 14 | 15 | forward 5 16 | down 5 17 | forward 8 18 | up 3 19 | down 8 20 | forward 2 21 | 22 | 23 | ## Part 1 24 | 25 | Take the starting position and depth as 0 0. 26 | 27 | ```q 28 | q)forward:1 0*; down:0 1*; up:0 -1* 29 | q)show c:value each read0`$":test/02.txt" 30 | 5 0 31 | 0 5 32 | 8 0 33 | 0 -3 34 | 0 8 35 | 2 0 36 | ``` 37 | 38 | The final position and depth are simply the sum of `c` and the answer to part 1 is their product. 39 | 40 | ```q 41 | q)prd sum c 42 | 150 43 | ``` 44 | 45 | ## Part 2 46 | 47 | Part 2 complicates the picture. The first column of `c` still describes forward movements. But we now need to calculate ‘aim’. Up and Down now adjust aim. Depth changes by the product of forward motion and aim. 48 | 49 | A table can help us to think this through. 50 | 51 | ```q 52 | q)crs:{select cmd:x,fwd,ud from flip`fwd`ud!flip value each x}read0`$":test/02.txt" 53 | q)update aim:sums ud from `crs 54 | `crs 55 | q)update down:fwd*aim from `crs 56 | `crs 57 | q)show crs 58 | cmd fwd ud aim down 59 | --------------------------- 60 | "forward 5" 5 0 0 0 61 | "down 5" 0 5 5 0 62 | "forward 8" 8 0 5 40 63 | "up 3" 0 -3 2 0 64 | "down 8" 0 8 10 0 65 | "forward 2" 2 0 10 20 66 | ``` 67 | 68 | Now we have the changes in horizontal and vertical position ``crs[`fwd`down]`` and can simply sum for the final position. 69 | 70 | ```q 71 | q)sum each crs[`fwd`down] 72 | 15 60 73 | ``` 74 | 75 | But the `down` column is no more than the product of the `fwd` column and the accumulated sums of the `ud` column. We can express the whole thing in terms of the `fwd` and `ud` vectors. 76 | 77 | ```q 78 | q)fwd:`ud set'flip c / forward; up-down 79 | q)prd sum each(fwd;fwd*sums ud) 80 | 900 81 | ``` 82 | 83 | The repetition of `fwd` draws the eye. Isn’t `(fwd;fwd*sums ud)` just `fwd` multiplied by 1 and by `sums ud`? 84 | 85 | ```q 86 | q)prd sum fwd*1,'sums ud 87 | 900 88 | ``` 89 | 90 | Put another way, `(fwd;fwd*sums ud)` is `fwd` multiplied by `sums[ud]` zero and 1 times. 91 | 92 | ```q 93 | q)prd sum 1(sums[ud]*)\fwd 94 | 900 95 | ``` 96 | 97 | Or expressed as a function directly on the columns of `c` 98 | 99 | ```q 100 | prd sum {x*1,'sums y}. flip c 101 | ``` 102 | 103 | That reduces our complete solution to 104 | 105 | ```q 106 | forward:1 0*; down:0 1*; up:0 -1* 107 | c:value each read0`$":input/02.txt" 108 | a[`$"2-1"]:prd sum c 109 | a[`$"2-2"]:prd sum {x*1,'sums y}. flip c 110 | ``` -------------------------------------------------------------------------------- /aoc/2021/04-giant-squid.md: -------------------------------------------------------------------------------- 1 | # 4. Giant Squid 2 | 3 | > You're already almost 1.5km (almost a mile) below the surface of the ocean, already so deep that you can't see any sunlight. What you can see, however, is a giant squid that has attached itself to the outside of your submarine. 4 | > 5 | > Maybe it wants to play bingo? 6 | 7 | Advent of Code 2021 [Day 4](https://adventofcode.com/2021/day/4) 8 | 9 | --- 10 | 11 | The bingo boards are nicely readable in the text file, but we shall find them more tractable as vectors. 12 | 13 | ```q 14 | q)q:read0`$":test/04.txt" 15 | q)nums:value first q 16 | q)show boards:value each" "sv'(where 0=count each q)cut q 17 | 22 13 17 11 0 8 2 23 4 24 21 9 14 16 7 6 10 3 18 5 1 12 20 15 19 18 | 3 15 0 2 22 9 18 13 17 5 19 8 7 25 23 20 11 10 24 4 14 21 16 12 6 19 | 14 21 17 24 4 10 16 15 9 19 18 8 23 26 20 22 11 13 6 5 2 0 12 3 7 20 | ``` 21 | 22 | A perfectly sensible looping approach would follow real life. We would call each number and see if any board has won. 23 | 24 | We’re not going to do that. We’re going to call all the numbers and see where the wins occur. 25 | 26 | ```q 27 | s:(or\')boards=/:\:nums / states: call all the numbers in turn 28 | ``` 29 | 30 | The derived function `=/:\:` (Equal Each Right Each Left) gives us a cross-product on the Equal operator. The list `boards=/:\:nums` has an item for each board. Each item is a boolean matrix: a row for each of the called numbers, the columns corresponding to the board numbers. Here’s the first board with 1s flagging the numbers as they are called in turn. 31 | 32 | ```q 33 | q)first boards=/:\:nums 34 | 0000000000000010000000000b 35 | 0000000010000000000000000b 36 | 0000000000010000000000000b 37 | 0000000000000000000100000b 38 | 0001000000000000000000000b 39 | 0010000000000000000000000b 40 | .. 41 | ``` 42 | 43 | Of course, once a number is called, it stays called. 44 | 45 | ```q 46 | q)(or\)first boards=/:\:nums 47 | 0000000000000010000000000b 48 | 0000000010000010000000000b 49 | 0000000010010010000000000b 50 | 0000000010010010000100000b 51 | 0001000010010010000100000b 52 | 0011000010010010000100000b 53 | .. 54 | ``` 55 | 56 | That is just the first board. We want the same for every board. 57 | 58 | ```q 59 | s:(or\')boards=/:\:nums / states: call all the numbers in turn 60 | ``` 61 | 62 | How to tell if a board has won? Here is the state of board 0 after 9 numbers have been called. 63 | 64 | ```q 65 | q)s[0;9;] 66 | 0011101110011010000100000b 67 | ``` 68 | 69 | Has it won? 70 | 71 | ```q 72 | q)5 cut s[0;9;] 73 | 00111b 74 | 01110b 75 | 01101b 76 | 00001b 77 | 00000b 78 | ``` 79 | 80 | Clearly not. That would require all 1s on at least one row. Or a column. 81 | 82 | ```q 83 | q)any all each {x,flip x}5 cut s[0;9;] 84 | 0b 85 | ``` 86 | 87 | Now we can flag the wins. 88 | 89 | ```q 90 | q)show w:{any all each {x,flip x} 5 cut x}''[s] 91 | 000000000000011111111111111b 92 | 000000000000001111111111111b 93 | 000000000001111111111111111b 94 | ``` 95 | 96 | From this we can see that the third board is the first to win and the second is the last to win. Also that they win on (respectively) the 11th and 14th numbers called. 97 | 98 | ```q 99 | q)sum each not w 100 | 13 14 11i 101 | ``` 102 | 103 | So the state of the winning board is `s[2;11;]` 104 | 105 | ```q 106 | q)5 cut s[2;11;] 107 | 11111b 108 | 00010b 109 | 00100b 110 | 01001b 111 | 11001b 112 | q)sum boards[2] where not s[2;11;] / sum the unmarked numbers 113 | 188 114 | q)nums[11]*sum boards[2] where not s[2;11;] / board score 115 | 4512 116 | ``` 117 | 118 | That makes our complete solution: 119 | 120 | ```q 121 | q:read0`$":input/04.txt" 122 | nums:value first q 123 | boards:value each" "sv'(where 0=count each q)cut q 124 | 125 | s:(or\')boards=/:\:nums / states: call all the numbers in turn 126 | w:sum each not{any all each b,flip b:5 cut x}''[s] / find wins 127 | bs:{nums[x]*sum boards[y] where not s[y;x;]} / score for board y after xth number 128 | a[`$"4-1"]:bs . {m,x?m:min x} w / winning board score 129 | a[`$"4-2"]:bs . {m,x?m:max x} w / losing board score 130 | ``` 131 | 132 | This is a nice example of the ‘overcomputing’ characteristic of vector languages. Clearly, an efficient algorithm would stop when it reached the first win. Or, for Part 2, the last win. 133 | 134 | But sometimes it is convenient to calculate all the results and search them. And, with vector operations, sometimes it is faster as well. -------------------------------------------------------------------------------- /aoc/2021/05-hydrothermal-venture.md: -------------------------------------------------------------------------------- 1 | # 5. Hydrothermal Venture 2 | 3 | ![Hydrothermal vents](img/vents.jpg) 4 | 5 | > You come across a field of hydrothermal vents on the ocean floor! These vents constantly produce large, opaque clouds, so it would be best to avoid them if possible… 6 | 7 | Advent of Code 2021 [Day 5](https://adventofcode.com/2021/day/5) 8 | 9 | --- 10 | 11 | Each vent is defined by two co-ordinate pairs. We’ll represent the vents as a list of 2×2 matrices. 12 | 13 | ```q 14 | q)show vents:{value"(",ssr[;"->";";"]x,")"}each read0 `:test5.txt 15 | 0 9 5 9 16 | 8 0 0 8 17 | 9 4 3 4 18 | 2 2 2 1 19 | 7 0 7 4 20 | 6 4 2 0 21 | 0 9 2 9 22 | 3 4 1 4 23 | 0 0 8 8 24 | 5 5 8 2 25 | q)first vents 26 | 0 9 27 | 5 9 28 | ``` 29 | 30 | 31 | ## Part 1 32 | 33 | The second coords match so the first vent is a horizontal line through 34 | 35 | ```q 36 | 0 9 37 | 1 9 38 | 2 9 39 | 3 9 40 | 4 9 41 | 5 9 42 | ``` 43 | 44 | which we could express as `(range 0 5),'range 9 9`. We need only 45 | 46 | ```q 47 | q)rng:{x+til y-x-1} / ascending range 48 | q)range:{@[;x](reverse rng reverse@;rng;first)2 sv(=;<).\:x} 49 | q)range each (5 9;5 3;9 9) 50 | 5 6 7 8 9 51 | 5 4 3 52 | 9 53 | ``` 54 | 55 | to get the points crossed by a vent. 56 | 57 | Note how range tests its argument pair for both equality and ascending, takes the resulting boolean pair as a decimal and indexes a list of three functions – equivalent to a case statement. But we can do better. If we move the test for equality into rng, both functions can be expressed with the ternary conditional Cond. 58 | 59 | ```q 60 | q)rng:{$[x=y;x;x+til y-x-1]}. / range (not descending) 61 | q)range:{$[.[>]x;reverse rng reverse x;rng x]} 62 | q)pts:{.[,']range each flip x} 63 | q)([]v:vents;p:pts each vents) 64 | v p 65 | --------------------------------------------- 66 | 0 9 5 9 (0 9;1 9;2 9;3 9;4 9;5 9) 67 | 8 0 0 8 (8 0;7 1;6 2;5 3;4 4;3 5;2 6;1 7;0 8) 68 | 9 4 3 4 (9 4;8 4;7 4;6 4;5 4;4 4;3 4) 69 | 2 2 2 1 (2 2;2 1) 70 | 7 0 7 4 (7 0;7 1;7 2;7 3;7 4) 71 | 6 4 2 0 (6 4;5 3;4 2;3 1;2 0) 72 | 0 9 2 9 (0 9;1 9;2 9) 73 | 3 4 1 4 (3 4;2 4;1 4) 74 | 0 0 8 8 (0 0;1 1;2 2;3 3;4 4;5 5;6 6;7 7;8 8) 75 | 5 5 8 2 (5 5;6 4;7 3;8 2) 76 | ``` 77 | 78 | We notice with satisfaction that `pts` finds the points for diagonal vents as well as vertical and horizontal ones. 79 | 80 | Find the points for just horizontal and vertical vents: 81 | 82 | ```q 83 | q)vents where{any .[=]x}each vents 84 | 0 9 5 9 85 | 9 4 3 4 86 | 2 2 2 1 87 | 7 0 7 4 88 | 0 9 2 9 89 | 3 4 1 4 90 | 91 | q)pts each vents where{any .[=]x}each vents 92 | (0 9;1 9;2 9;3 9;4 9;5 9) 93 | (9 4;8 4;7 4;6 4;5 4;4 4;3 4) 94 | (2 2;2 1) 95 | (7 0;7 1;7 2;7 3;7 4) 96 | (0 9;1 9;2 9) 97 | (3 4;2 4;1 4) 98 | 99 | q)count each group raze pts each vents where{any .[=]x}each vents 100 | 0 9| 2 101 | 1 9| 2 102 | 2 9| 2 103 | 3 9| 1 104 | 4 9| 1 105 | 5 9| 1 106 | 9 4| 1 107 | 8 4| 1 108 | 7 4| 2 109 | 6 4| 1 110 | 5 4| 1 111 | 4 4| 1 112 | 3 4| 2 113 | 2 2| 1 114 | 2 1| 1 115 | 7 0| 1 116 | 7 1| 1 117 | 7 2| 1 118 | 7 3| 1 119 | 2 4| 1 120 | 1 4| 1 121 | ``` 122 | 123 | And count the points where vents overlap. 124 | 125 | ```q 126 | q)plot:{count each group raze pts each x} 127 | q)chp:{count where 1";";"]x,")"}each read0 `$":input/05.txt" 162 | rng:{$[x=y;x;x+til y-x-1]}. / range (ascending only) 163 | range:{$[.[>]x;reverse rng reverse x;rng x]} 164 | pts:{.[,']range each flip x} / points of a vent 165 | plot:{count each group raze pts each x} 166 | chp:{count where 1 A massive school of glowing lanternfish swims past. They must spawn quickly to reach such large numbers – maybe **exponentially** quickly? You should model their growth rate to be sure… 6 | 7 | Advent of Code 2021 [Day 6](https://adventofcode.com/2021/day/6) 8 | 9 | --- 10 | 11 | ## Part 1 12 | 13 | It’s tempting to model the lanternfish population as a vector of timer states, subtracting 1 on each day, resetting each 0 to 6 and appending an 8. That lets us model progress day by day. 14 | 15 | ```q 16 | q)3{,[;sum[n]#8] (x-1)+7*n:x=0}\3 4 3 1 2 17 | 3 4 3 1 2 18 | 2 3 2 0 1 19 | 1 2 1 6 0 8 20 | 0 1 0 5 6 7 8 21 | ``` 22 | 23 | And count them after 18 and 80 days. 24 | 25 | ```q 26 | q)count 18{,[;sum[n]#8] (x-1)+7*n:x=0}/3 4 3 1 2 27 | 26 28 | q)count 80{,[;sum[n]#8] (x-1)+7*n:x=0}/3 4 3 1 2 29 | 5934 30 | ``` 31 | 32 | 33 | ## Part 2 34 | 35 | But all this gets out of hand over 256 days as the vector count exceeds 26 billion. 36 | 37 | A vector is an ordered list, but we do not need the lanternfish in any order. We need only represent how many fish have their timers in a given state. We could do this with a dictionary. 38 | 39 | ```q 40 | q)count each group 3 4 3 1 2 41 | 3| 2 42 | 4| 1 43 | 1| 1 44 | 2| 1 45 | ``` 46 | 47 | But even this is more information than we need. There are only nine possible timer values. A vector of nine integers will number the fish at each timer state. 48 | 49 | ```q 50 | q)show lf:@[9#0;;1+]3 4 3 1 2 / lanternfish school 51 | 0 1 1 2 1 0 0 0 0 52 | ``` 53 | 54 | Notice that, in the application of [Amend At](https://code.kx.com/q/ref/amend/) above, the index vector `3 4 3 1 2` contains two 3s. The unary third argument of Amend At, `1+`, is applied twice at index 3. The iteration is implicit in Amend At and need not be specified. 55 | 56 | Now we represent a day’s count-down with a `1 rotate`, which happily rotates the fish with expired timers round to position 8. But position 8 represents newly spawned fish. So we need also to reset their parents’ timers by adding them at position 6. 57 | 58 | ```q 59 | q)3 {@[1 rotate x;6;+;first x]}\ lf 60 | 0 1 1 2 1 0 0 0 0 61 | 1 1 2 1 0 0 0 0 0 62 | 1 2 1 0 0 0 1 0 1 63 | 2 1 0 0 0 1 1 1 1 64 | ``` 65 | 66 | Above, we used the Scan form of the [Do](https://code.kx.com/q/ref/accumulators/#do) iterator to apply the unary lambda `{@[1 rotate x;6;+;first x]}`, returning a list of the results of 0, 1, 2, and 3 iterations. 67 | 68 | After the required iterations, count the fish with `sum`. 69 | 70 | ```q 71 | q)sum 256{@[1 rotate x;6;+;x 0]}/ lf 72 | 26984457539 73 | ``` 74 | 75 | Above, we used the Over form of the Do iterator to evaluate the lambda 256 times. (Unlike the Scan form, the Over form returns the result of only the last iteration.) 76 | 77 | Our complete solution: 78 | 79 | ```q 80 | lf:@[9#0;;1+] value first read0`$":input/06.txt" / lanternfish school 81 | a[`$("6-1";"6-2")]:sum each @[;80 256] 256{@[1 rotate x;6;+;first 0]}\lf 82 | ``` 83 | 84 | Above, rather than run the same Do iteration first 80 then 256 times, we have run it 256 times with Scan, then selected the 80th and 256th state vectors from the result. 85 | 86 | -------------------------------------------------------------------------------- /aoc/2021/09-smoke-basin.md: -------------------------------------------------------------------------------- 1 | # 9. Smoke Basin 2 | 3 | > These caves seem to be lava tubes. Parts are even still volcanically active; small hydrothermal vents release smoke into the caves that slowly settles like rain. 4 | 5 | Advent of Code 2021 [Day 9](https://adventofcode.com/2021/day/9) 6 | 7 | --- 8 | 9 | 10 | ```q 11 | hm:read0`$":input/09.txt" / heightmap 12 | shp:{count@/:1 first\x} / shape of a matrix 13 | drop:{[rc;m]rc[0]_ rc[1]_'m} / 2-D Drop 14 | pad:{[rc;m]flip rc[0]$'flip rc[1]$m} / 2d Pad 15 | am:(1 0;-1 0;0 1;0 -1) / adjacency matrix 16 | lp:all hm You ask the submarine to determine the best route out of the deep-sea cave, but it only replies: 4 | > 5 | > > Syntax error in navigation subsystem on line: all of them 6 | 7 | Advent of Code 2021 [Day 10](https://adventofcode.com/2021/day/10) 8 | 9 | --- 10 | 11 | ```q 12 | subsys:read0`$":input/10.txt" 13 | tkn:"()[]{}<>" / tokens 14 | opn:"([{<"; cls:")]}>" 15 | 16 | prs:{[str;stk] c:str 0; / parse string with stack 17 | $[c in opn;(1_str;stk,c);opn[cls?c]=last stk;(1_str;-1 _ stk);(str;stk)] }. 18 | 19 | pr:('[prs/;(;"")]) each subsys 20 | a[`$"10-1"]:sum (cls!3 57 1197 25137) 2 first'/pr 21 | 22 | com:(opn!cls)reverse each{y where 0=ce x}. flip pr / completions 23 | a[`$"10-2"]:"j"$med({y+5*x}/)each 1+cls?com 24 | ``` -------------------------------------------------------------------------------- /aoc/2021/11-dumbo-octopus.md: -------------------------------------------------------------------------------- 1 | # 11. Dumbo Octopus 2 | 3 | > You enter a large cavern full of rare bioluminescent dumbo octopuses! They seem to not like the Christmas lights on your submarine, so you turn them off for now. 4 | 5 | Advent of Code 2021 [Day 11](https://adventofcode.com/2021/day/11) 6 | 7 | --- 8 | 9 | ```q 10 | o:"0123456789"?raze oct:read0`$":input/11.txt" / octopus vector 11 | off:except[;enlist 0 0]{x cross x}til[3]-1 / neighbor offsets 12 | 13 | nbr:{c:off+\:y;x sv/:c where all flip[c]within'0,'x-1}[shp oct] 14 | each .[cross]til each shp oct / neighbor indexes for o 15 | 16 | flash:{i:where[x>9]except y; (@[x;raze nbr i;1+];y,i)}. / flash x where hot except at y 17 | step:{({x*x<10};'[y+;count])@'flash over (x+1;0#0)}. / [energy;# accumulated flashes] 18 | 19 | a[`$"11-1"]:@[;1] 100 step/(o;0) 20 | a[`$"11-2"]:-[;1] count {any 0 With your submarine’s subterranean subsystems subsisting suboptimally, the only way you’re getting out of this cave anytime soon is by finding a path yourself. Not just *a* path - the only way to know if you’ve found the best path is to find *all* of them. 4 | 5 | Advent of Code 2021 [Day 12](https://adventofcode.com/2021/day/12) 6 | 7 | --- 8 | 9 | ```q 10 | map:.[!](key;'[except'[;`start];value])@\:delete end from group 11 | .[!]flip{x,reverse each x}`$"-"vs/:read0`$":input/12.txt" 12 | 13 | sc:{x where(first each string x)in .Q.a}key[map]except`start / small caves 14 | 15 | xplr:{[m;sc;f;r] / explore map; small caves; routes 16 | (r where`end=last each r),raze r,/:'(m last each r)except'r f\:sc 17 | } [map;sc;] 18 | 19 | a[`$"12-1"]:count (xplr[inter]/) 1 1#`start 20 | a[`$"12-2"]:count (xplr[{$[2 in(ce group x)@y;x inter y;()]}]/) 1 1#`start 21 | ``` -------------------------------------------------------------------------------- /aoc/2021/13-transparent-origami.md: -------------------------------------------------------------------------------- 1 | # 13. Transparent Origami 2 | 3 | > You reach another volcanically active part of the cave. It would be nice if you could do some kind of thermal imaging so you could tell ahead of time which caves are too hot to safely enter. 4 | 5 | Advent of Code 2021 [Day 13](https://adventofcode.com/2021/day/13) 6 | 7 | --- 8 | 9 | ```q 10 | `pts`folds set'('[reverse;value]';1_)@'{(0,where 0=ce x)_ x}read0`$":input/13.txt" 11 | p1:((1+max pts)#0b) .[;;:;1b]/pts / page one 12 | fold:{f:(::;flip)@"yx"?y@11;n:value 13_y;f .[or](::;reverse)@'(1 neg\n)#\:f x} / fold x according to y 13 | a[`$"13-1"]:sum raze fold[p1;first folds] 14 | ``` -------------------------------------------------------------------------------- /aoc/2021/14-extended-polymerization.md: -------------------------------------------------------------------------------- 1 | # 14. Extended Polymerization 2 | 3 | > The incredible pressures at this depth are starting to put a strain on your submarine. The submarine has polymerization equipment that would produce suitable materials to reinforce the submarine, and the nearby volcanically-active caves should even have the necessary input elements in sufficient quantities. 4 | 5 | Advent of Code 2021 [Day 14](https://adventofcode.com/2021/day/14) 6 | 7 | --- 8 | 9 | ```q 10 | `pt`pir set'(first;2_)@\:read0:":input/14.txt" / polymer template; polymer insertion rules 11 | 12 | / Stephen Taylor 13 | ird:.[!]flip{(x 0 1;lower[x 6],x 1)}each pir / insertion rules dictionary 14 | air:{upper 1_raze {$[count r:ird o:y,x;r;o]} prior x} / apply insertion rules 15 | a[`$"14-1"]:.[-](max;min)@\:ce group 10 air/pt 16 | 17 | / András Dőtsch 18 | pairs:2#'-2_(1_)\ / (composition) 19 | pm:{x!x}pairs pt 20 | pm,:(!). flip pir@\:(0 1;0 6 1) 21 | f:{""{(-1_x),pm y}/pairs x} 22 | ws:count@'group@ 23 | score:(-).(max;min)@\: 24 | a[`$"14-1a"]:score ws 10 f/ pt 25 | 26 | T:ws pairs pt 27 | PM:{x!{(1#x)!1#1}@'x}pairs pt 28 | PM,:{x!1 1}@' (!). flip pir@\:(0 1;(0 6;6 1)) 29 | F:{value[x] wsum PM key x} 30 | WS:{div[;2] (ws(first pt;last pt)) + value[x] wsum ws@'key x} 31 | a[`$"14-2a"]:score WS 40 F/ T 32 | ``` -------------------------------------------------------------------------------- /aoc/2021/README.md: -------------------------------------------------------------------------------- 1 | The birth of the cool 2 | ===================== 3 | This year’s [Advent of Code](https://adventofcode.com/) has raised the excitement level in the vector dojo because the puzzles are particularly susceptible to vector solutions. 4 | 5 | We nod to code golfers who seek the shortest solutions, and to others who pursue the fastest. But in the dojo we seek the most ‘vector-ish’ solutions. That’s admittedly a bit vague, because it is at bottom an aesthetic criterion – often pronounced “cool”. 6 | 7 | Feel free to chime in with comments and alternatives: what follows is unlikely to be the last word in cool. -------------------------------------------------------------------------------- /aoc/2021/img/lanternfish.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/aoc/2021/img/lanternfish.jpg -------------------------------------------------------------------------------- /aoc/2021/img/vents.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/aoc/2021/img/vents.jpg -------------------------------------------------------------------------------- /aoc/2021/input/06.txt: -------------------------------------------------------------------------------- 1 | 2,3,1,3,4,4,1,5,2,3,1,1,4,5,5,3,5,5,4,1,2,1,1,1,1,1,1,4,1,1,1,4,1,3,1,4,1,1,4,1,3,4,5,1,1,5,3,4,3,4,1,5,1,3,1,1,1,3,5,3,2,3,1,5,2,2,1,1,4,1,1,2,2,2,2,3,2,1,2,5,4,1,1,1,5,5,3,1,3,2,2,2,5,1,5,2,4,1,1,3,3,5,2,3,1,2,1,5,1,4,3,5,2,1,5,3,4,4,5,3,1,2,4,3,4,1,3,1,1,2,5,4,3,5,3,2,1,4,1,4,4,2,3,1,1,2,1,1,3,3,3,1,1,2,2,1,1,1,5,1,5,1,4,5,1,5,2,4,3,1,1,3,2,2,1,4,3,1,1,1,3,3,3,4,5,2,3,3,1,3,1,4,1,1,1,2,5,1,4,1,2,4,5,4,1,5,1,5,5,1,5,5,2,5,5,1,4,5,1,1,3,2,5,5,5,4,3,2,5,4,1,1,2,4,4,1,1,1,3,2,1,1,2,1,2,2,3,4,5,4,1,4,5,1,1,5,5,1,4,1,4,4,1,5,3,1,4,3,5,3,1,3,1,4,2,4,5,1,4,1,2,4,1,2,5,1,1,5,1,1,3,1,1,2,3,4,2,4,3,1 2 | -------------------------------------------------------------------------------- /aoc/2021/input/07.txt: -------------------------------------------------------------------------------- 1 | 1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,928,1690,960,74,66,40,867,580,20,226,21,10,230,23,532,443,260,31,10,387,1050,216,85,307,38,1132,1289,98,1228,20,908,1740,393,321,18,26,389,1002,1347,307,1483,1108,60,1116,1395,56,98,652,745,511,107,806,801,881,1619,404,151,1034,675,393,774,942,771,1027,1609,59,994,300,618,1457,531,491,1470,1089,536,229,150,46,0,310,1114,924,414,163,333,1797,390,240,10,576,421,452,235,26,1128,137,260,92,1174,757,1040,265,70,658,913,72,21,144,1567,1471,956,375,63,1633,862,664,1039,6,1318,624,169,667,523,449,1130,1314,0,860,0,599,209,14,389,875,414,368,843,424,1094,173,363,575,1243,296,179,431,587,89,80,274,202,752,317,829,1116,8,83,371,556,21,1042,270,521,374,76,0,274,417,147,1415,356,1717,1281,184,667,1169,1185,1881,376,448,92,1252,25,98,1563,535,14,180,327,341,1231,1160,253,1530,1513,152,382,69,528,1417,300,5,966,1412,1329,1527,109,416,172,1073,216,315,357,446,106,279,351,56,1097,303,867,1447,768,766,9,226,761,27,229,35,286,358,205,36,176,233,800,1839,268,321,30,280,105,21,315,1265,0,1172,208,352,120,673,693,449,670,246,15,380,67,168,408,364,1115,1018,601,265,59,52,329,1277,19,4,706,66,776,25,202,356,343,375,27,339,1424,418,184,232,522,83,176,61,646,1150,433,120,33,1380,348,486,669,1049,161,1372,817,13,387,629,808,504,291,119,217,806,177,228,487,872,420,803,19,386,1398,35,1509,955,213,1385,40,184,820,404,1670,723,613,1443,982,263,75,652,57,833,991,296,37,62,1093,1727,8,298,717,206,4,470,170,830,150,350,145,690,180,858,334,20,679,9,37,552,959,71,32,214,344,5,27,1810,628,1622,476,1255,330,552,334,785,212,17,1062,491,41,261,60,241,1479,502,28,1561,435,22,349,12,373,182,463,222,50,709,484,146,400,630,216,78,1239,1512,56,870,1082,1343,901,45,332,602,176,991,439,639,600,215,14,316,202,1396,672,908,580,805,282,1420,493,216,1686,12,240,1216,797,109,308,224,424,1260,453,673,380,13,3,842,389,1421,350,308,634,187,1707,173,1174,597,562,1020,76,199,579,1045,335,465,37,70,784,248,137,35,466,298,108,1553,105,99,27,875,936,107,1129,609,1144,378,89,549,556,184,1016,11,568,953,8,595,0,670,651,684,172,266,505,103,68,37,392,289,259,1295,7,558,493,1118,13,522,378,595,96,1300,978,578,24,316,4,1316,20,39,194,99,236,2,1346,108,68,317,85,822,602,944,535,54,160,455,954,59,257,1511,232,1377,38,191,104,1336,624,1140,512,1384,332,54,61,207,75,1153,93,550,741,801,13,20,8,1144,567,97,675,1000,10,228,197,51,901,77,521,1871,588,639,670,45,85,843,40,1039,1074,531,1312,60,311,875,1429,917,420,1155,411,218,630,64,374,196,955,917,718,689,900,1419,283,296,529,811,841,459,163,514,63,1150,151,97,919,940,291,873,140,63,922,62,741,260,26,491,731,26,862,180,967,892,546,104,397,293,119,48,46,91,46,1369,73,159,347,13,742,6,103,459,152,533,5,314,825,189,164,9,170,610,156,1420,672,218,1412,1201,1862,202,154,1449,9,32,78,146,1277,281,288,493,31,9,425,633,177,1056,248,711,429,51,370,700,40,69,316,600,187,77,289,39,779,1001,218,1574,1178,260,1206,143,228,1094,810,1098,383,335,36,64,1340,32,536,6,117,55,837,34,273,412,417,741,215,1267,1233,1088,1211,64,6,628,610,213,279,212,274,362,290,191,390,512,1030,892,5,615,575,740,111,119,29,45,439,1342,1167,1239,1304,472,380,56,1599,25,810,1011,21,640,210,558,102,7,270,75,31,134,183,360,270,197,316,6,174,145,326,336,761,703,1344,274,577,425,641,812,11,121,6,506,573,1393,0,287,606,76,595,753,495,669,13,143,241,103,567,693,1661,229,75,96,1521,150,12,562,1107,308,63,258,17,671,13,682,69,280,8,253,970,344,1016,655,489,1073,18,8,1713,96,193,709,112,510,109,118,106,546,241,1388,372,596,900,93,448,209,490,171,615,574,620,42,108,197,784,907,614,490,334,10,369,515,190,809,106,1105,398,423,356,576,83,477,41,1017,480,336,18,277,552,1322,575,449,3,571,123,298,356,743,427,26,305,1708,376,82,296,1341,933,372,35,1052,85,9,454 2 | -------------------------------------------------------------------------------- /aoc/2021/input/11.txt: -------------------------------------------------------------------------------- 1 | 1254117228 2 | 4416873224 3 | 8354381553 4 | 1372637614 5 | 5586538553 6 | 7213333427 7 | 3571362825 8 | 1681126243 9 | 8718312138 10 | 5254266347 -------------------------------------------------------------------------------- /aoc/2021/input/12.txt: -------------------------------------------------------------------------------- 1 | RT-start 2 | bp-sq 3 | em-bp 4 | end-em 5 | to-MW 6 | to-VK 7 | RT-bp 8 | start-MW 9 | to-hr 10 | sq-AR 11 | RT-hr 12 | bp-to 13 | hr-VK 14 | st-VK 15 | sq-end 16 | MW-sq 17 | to-RT 18 | em-er 19 | bp-hr 20 | MW-em 21 | st-bp 22 | to-start 23 | em-st 24 | st-end 25 | VK-sq 26 | hr-st -------------------------------------------------------------------------------- /aoc/2021/input/14.txt: -------------------------------------------------------------------------------- 1 | FNFPPNKPPHSOKFFHOFOC 2 | 3 | VS -> B 4 | SV -> C 5 | PP -> N 6 | NS -> N 7 | BC -> N 8 | PB -> F 9 | BK -> P 10 | NV -> V 11 | KF -> C 12 | KS -> C 13 | PV -> N 14 | NF -> S 15 | PK -> F 16 | SC -> F 17 | KN -> K 18 | PN -> K 19 | OH -> F 20 | PS -> P 21 | FN -> O 22 | OP -> B 23 | FO -> C 24 | HS -> F 25 | VO -> C 26 | OS -> B 27 | PF -> V 28 | SB -> V 29 | KO -> O 30 | SK -> N 31 | KB -> F 32 | KH -> C 33 | CC -> B 34 | CS -> C 35 | OF -> C 36 | FS -> B 37 | FP -> H 38 | VN -> O 39 | NB -> N 40 | BS -> H 41 | PC -> H 42 | OO -> F 43 | BF -> O 44 | HC -> P 45 | BH -> S 46 | NP -> P 47 | FB -> C 48 | CB -> H 49 | BO -> C 50 | NN -> V 51 | SF -> N 52 | FC -> F 53 | KK -> C 54 | CN -> N 55 | BV -> F 56 | FK -> C 57 | CF -> F 58 | VV -> B 59 | VF -> S 60 | CK -> C 61 | OV -> P 62 | NC -> N 63 | SS -> F 64 | NK -> V 65 | HN -> O 66 | ON -> P 67 | FH -> O 68 | OB -> H 69 | SH -> H 70 | NH -> V 71 | FF -> B 72 | HP -> B 73 | PO -> P 74 | HB -> H 75 | CH -> N 76 | SN -> P 77 | HK -> P 78 | FV -> H 79 | SO -> O 80 | VH -> V 81 | BP -> V 82 | CV -> P 83 | KP -> K 84 | VB -> N 85 | HV -> K 86 | SP -> N 87 | HO -> P 88 | CP -> H 89 | VC -> N 90 | CO -> S 91 | BN -> H 92 | NO -> B 93 | HF -> O 94 | VP -> K 95 | KV -> H 96 | KC -> F 97 | HH -> C 98 | BB -> K 99 | VK -> P 100 | OK -> C 101 | OC -> C 102 | PH -> H -------------------------------------------------------------------------------- /aoc/2021/test/01.txt: -------------------------------------------------------------------------------- 1 | 199 2 | 200 3 | 208 4 | 210 5 | 200 6 | 207 7 | 240 8 | 269 9 | 260 10 | 263 -------------------------------------------------------------------------------- /aoc/2021/test/02.txt: -------------------------------------------------------------------------------- 1 | forward 5 2 | down 5 3 | forward 8 4 | up 3 5 | down 8 6 | forward 2 -------------------------------------------------------------------------------- /aoc/2021/test/03.txt: -------------------------------------------------------------------------------- 1 | 00100 2 | 11110 3 | 10110 4 | 10111 5 | 10101 6 | 01111 7 | 00111 8 | 11100 9 | 10000 10 | 11001 11 | 00010 12 | 01010 -------------------------------------------------------------------------------- /aoc/2021/test/04.txt: -------------------------------------------------------------------------------- 1 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 2 | 3 | 22 13 17 11 0 4 | 8 2 23 4 24 5 | 21 9 14 16 7 6 | 6 10 3 18 5 7 | 1 12 20 15 19 8 | 9 | 3 15 0 2 22 10 | 9 18 13 17 5 11 | 19 8 7 25 23 12 | 20 11 10 24 4 13 | 14 21 16 12 6 14 | 15 | 14 21 17 24 4 16 | 10 16 15 9 19 17 | 18 8 23 26 20 18 | 22 11 13 6 5 19 | 2 0 12 3 7 -------------------------------------------------------------------------------- /aoc/2021/test/05.txt: -------------------------------------------------------------------------------- 1 | 0,9 -> 5,9 2 | 8,0 -> 0,8 3 | 9,4 -> 3,4 4 | 2,2 -> 2,1 5 | 7,0 -> 7,4 6 | 6,4 -> 2,0 7 | 0,9 -> 2,9 8 | 3,4 -> 1,4 9 | 0,0 -> 8,8 10 | 5,5 -> 8,2 -------------------------------------------------------------------------------- /aoc/2021/test/06.txt: -------------------------------------------------------------------------------- 1 | 3,4,3,1,2 -------------------------------------------------------------------------------- /aoc/2021/test/07.txt: -------------------------------------------------------------------------------- 1 | 16,1,2,0,4,2,7,1,2,14 -------------------------------------------------------------------------------- /aoc/2021/test/08.txt: -------------------------------------------------------------------------------- 1 | be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe 2 | edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc 3 | fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg 4 | fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb 5 | aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea 6 | fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb 7 | dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe 8 | bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef 9 | egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb 10 | gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce -------------------------------------------------------------------------------- /aoc/2021/test/09.txt: -------------------------------------------------------------------------------- 1 | 2199943210 2 | 3987894921 3 | 9856789892 4 | 8767896789 5 | 9899965678 -------------------------------------------------------------------------------- /aoc/2021/test/10.txt: -------------------------------------------------------------------------------- 1 | [({(<(())[]>[[{[]{<()<>> 2 | [(()[<>])]({[<{<<[]>>( 3 | {([(<{}[<>[]}>{[]{[(<()> 4 | (((({<>}<{<{<>}{[]{[]{} 5 | [[<[([]))<([[{}[[()]]] 6 | [{[{({}]{}}([{[{{{}}([] 7 | {<[[]]>}<{[{[{[]{()[[[] 8 | [<(<(<(<{}))><([]([]() 9 | <{([([[(<>()){}]>(<<{{ 10 | <{([{{}}[<[[[<>{}]]]>[]] -------------------------------------------------------------------------------- /aoc/2021/test/11.txt: -------------------------------------------------------------------------------- 1 | 5483143223 2 | 2745854711 3 | 5264556173 4 | 6141336146 5 | 6357385478 6 | 4167524645 7 | 2176841721 8 | 6882881134 9 | 4846848554 10 | 5283751526 -------------------------------------------------------------------------------- /aoc/2021/test/12.txt: -------------------------------------------------------------------------------- 1 | start-A 2 | start-b 3 | A-c 4 | A-b 5 | b-d 6 | A-end 7 | b-end -------------------------------------------------------------------------------- /aoc/2021/test/13.txt: -------------------------------------------------------------------------------- 1 | 6,10 2 | 0,14 3 | 9,10 4 | 0,3 5 | 10,4 6 | 4,11 7 | 6,0 8 | 6,12 9 | 4,1 10 | 0,13 11 | 10,12 12 | 3,4 13 | 3,0 14 | 8,4 15 | 1,10 16 | 2,14 17 | 8,10 18 | 9,0 19 | 20 | fold along y=7 21 | fold along x=5 -------------------------------------------------------------------------------- /aoc/2021/test/14.txt: -------------------------------------------------------------------------------- 1 | NNCB 2 | 3 | CH -> B 4 | HH -> N 5 | CB -> H 6 | NH -> C 7 | HB -> C 8 | HC -> B 9 | HN -> C 10 | NN -> C 11 | BH -> H 12 | NC -> B 13 | NB -> B 14 | BN -> B 15 | BB -> N 16 | BC -> B 17 | CC -> N 18 | CN -> C -------------------------------------------------------------------------------- /aoc/2021/test/15.txt: -------------------------------------------------------------------------------- 1 | 1163751742 2 | 1381373672 3 | 2136511328 4 | 3694931569 5 | 7463417111 6 | 1319128137 7 | 1359912421 8 | 3125421639 9 | 1293138521 10 | 2311944581 -------------------------------------------------------------------------------- /aoc/2022/01.md: -------------------------------------------------------------------------------- 1 | # Day 1: Calorie Counting 2 | 3 | 4 | > Santa’s reindeer typically eat regular reindeer food, but they need a lot of magical energy to deliver presents on Christmas. For that, their favorite snack is a special type of star fruit that only grows deep in the jungle. The Elves have brought you on their annual expedition to the grove where the fruit grows. 5 | 6 | Advent of Code 2022 [Day 1](https://adventofcode.com/2022/day/1) 7 | 8 | ## Ingestion 9 | 10 | ```q 11 | inp: read0`:input/01.txt 12 | loads: sum each{(0,where null x)_ x}"I"$inp 13 | ``` 14 | 15 | Above, `read0` returns a list of strings that [Tok](https://code.kx.com/q/ref/tok) interprets as integers. 16 | Note that Tok iterates implicitly through the strings; no Each is needed. 17 | 18 | Cillian found a way to avoid the `sum`. 19 | 20 | ```q 21 | value each"++"vs"+"sv inp 22 | ``` 23 | 24 | This is cunning. He uses `"+"` to join the strings, which leaves `"++"` separating the records, which he can then evaluate with `value each`. 25 | 26 | ```q 27 | q)"+"sv read0 `:test/01.txt 28 | "1000+2000+3000++4000++5000+6000++7000+8000+9000++10000" 29 | q)"++"vs"+"sv read0 `:test/01.txt 30 | "1000+2000+3000" 31 | "4000" 32 | "5000+6000" 33 | "7000+8000+9000" 34 | "10000" 35 | ``` 36 | 37 | Nick Psaris read the input in binary and cast to character 38 | 39 | ```q 40 | q)"\n\n"vs"c"$read1 `:test/01.txt 41 | "1000\n2000\n3000" 42 | "4000" 43 | "5000\n6000" 44 | "7000\n8000\n9000" 45 | "10000" 46 | ``` 47 | 48 | and used `get` (a synonym of `value`) to evaluate. 49 | 50 | ```q 51 | loads:(sum get::) each "\n\n"vs"c"$read1 `:test/01.txt 52 | ``` 53 | 54 | Sean Ang used string search-and-replace to wrangle the input. 55 | 56 | ```q 57 | q)ssr[;" ";";sum "]" "sv read0 `:test/01.txt 58 | "1000 2000 3000;sum 4000;sum 5000 6000;sum 7000 8000 9000;sum 10000" 59 | q)value {"(sum ",x,")"} ssr[;" ";";sum "]" "sv read0 `:test/01.txt 60 | 6000 4000 11000 24000 10000 61 | ``` 62 | 63 | ### Cillian’s straight vector ingestion 64 | 65 | A ‘straight’ vector solution avoids partitioning vectors into lists of lists. 66 | Because q handles vectors efficiently, straight-vector solutions are often very fast. 67 | 68 | Cillian found one using sorts and Match Each Prior (`~':`). 69 | 70 | ```q 71 | q)show s:sums"J"$read0`:test/01.txt 72 | 1000 3000 6000 6000 10000 10000 15000 21000 21000 28000 36000 45000 45000 55000 73 | q)(~':)s 74 | 00010100100010b 75 | q)s*(~':)s 76 | 0 0 0 6000 0 10000 0 0 21000 0 0 0 45000 0 77 | q)desc deltas asc s*(~':)s 78 | 24000 11000 6000 4000 0 0 0 0 0 0 0 0 0 0 79 | ``` 80 | 81 | ```q 82 | loads:desc deltas asc s*(~':)s:sums"J"$read0`:test/01.txt 83 | ``` 84 | 85 | And we are happy to ignore the trailing zeroes. 86 | 87 | Once the loads have been calculated, the rest is trivial. 88 | 89 | 90 | ## Solutions 91 | 92 | ```q 93 | max loads /part 1 94 | sum 3#desc loads /part 2 95 | ``` 96 | 97 | Or, since we have to sort for Part 2 anyway, we can lose the `max`. 98 | 99 | 100 | ```q 101 | (first;sum 3#::)@\:desc loads 102 | ``` 103 | 104 | 105 | ## Contributors 106 | 107 | * Sean Ang 108 | * Cillian Reilly 109 | * Nick Psaris 110 | * Stephen Taylor 111 | -------------------------------------------------------------------------------- /aoc/2022/02.md: -------------------------------------------------------------------------------- 1 | # Day 2: Rock Paper Scissors 2 | 3 | > The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the snack storage, a giant Rock Paper Scissors tournament is already in progress. 4 | 5 | Advent of Code 2022 [Day 2](https://adventofcode.com/2022/day/2) 6 | 7 | ## Ingestion 8 | 9 | The strategy is the first and third columns of the input. 10 | 11 | ```q 12 | q)show strategy: .[;(::;0 2)] inp:read0 `:test/02.txt 13 | "AY" 14 | "BX" 15 | "CZ" 16 | ``` 17 | 18 | ## Solution 19 | 20 | We could code the rules of Rock Paper Scissors as a function `ldw` that maps each pair to lose/draw/win. But there are only nine possible pairs. 21 | A dictionary has fewer moving parts. 22 | 23 | ```q 24 | q)show ldw:3*cut[2;"BXCYAZAXBYCZCXAYBZ"]!til[3]where 3#3 / lose; draw; win 25 | "BX"| 0 26 | "CY"| 0 27 | "AZ"| 0 28 | "AX"| 3 29 | "BY"| 3 30 | "CZ"| 3 31 | "CX"| 6 32 | "AY"| 6 33 | "BZ"| 6 34 | ``` 35 | 36 | To which we add the score for the response choice. 37 | 38 | ```q 39 | q)show score:ldw+1+"XYZ"?(key ldw)[;1] 40 | "BX"| 1 41 | "CY"| 2 42 | "AZ"| 3 43 | "AX"| 4 44 | "BY"| 5 45 | "CZ"| 6 46 | "CX"| 7 47 | "AY"| 8 48 | "BZ"| 9 49 | 50 | q)score each strategy 51 | 8 1 6 52 | ``` 53 | 54 | But now we see that we can replace the dictionary with Find. 55 | 56 | ```q 57 | q)1+string[`BX`CY`AZ`AX`BY`CZ`CX`AY`BZ]?strategy 58 | 8 1 6 59 | ``` 60 | 61 | And we can solve Part 1 with 62 | 63 | ```q 64 | rounds: string`BX`CY`AZ`AX`BY`CZ`CX`AY`BZ 65 | score: sum 1+ rounds? :: 66 | score strategy 67 | ``` 68 | 69 | 70 | ## Part 2 71 | 72 | Part 2 introduces a preliminary mapping before we can score. 73 | 74 | ```q 75 | q)show play:rounds!rounds[;0],'"XZYZYXYXZ" 76 | "BX"| "BX" 77 | "CY"| "CZ" 78 | "AZ"| "AY" 79 | "AX"| "AZ" 80 | "BY"| "BY" 81 | "CZ"| "CX" 82 | "CX"| "CY" 83 | "AY"| "AX" 84 | "BZ"| "BZ" 85 | 86 | q)score play strategy 87 | 12 88 | ``` 89 | 90 | Or, for Parts 1 & 2 together 91 | 92 | ```q 93 | q)score each 1 play\ strategy 94 | 15 12 95 | ``` 96 | 97 | To do: discuss solutions from András, Nick, Attila 98 | -------------------------------------------------------------------------------- /aoc/2022/03.md: -------------------------------------------------------------------------------- 1 | # Day 3: Rucksack Reorganization 2 | 3 | > One Elf has the important job of loading all of the rucksacks with supplies for the jungle journey. Unfortunately, that Elf didn't quite follow the packing instructions, and so a few items now need to be rearranged. 4 | 5 | Advent of Code 2022 [Day 3](https://adventofcode.com/2022/day/3) 6 | 7 | ```q 8 | inp: read0`:input/03.txt 9 | ``` 10 | 11 | ## Part 1 12 | 13 | Each rucksack (line of `inp`) contains an even number of items and a single item that appears in both. 14 | We cut the list in two `{(2,count[x]div 2)#x}` and apply a binary `{first x where x in y}` to the halves to return the error. 15 | 16 | We project the binary and compose it with the unary. 17 | 18 | ```q 19 | err: {first x where x in y} . {(2,count[x]div 2)#x} :: / identify error 20 | ``` 21 | 22 | The item priorities are their indices in this string: 23 | 24 | ```q 25 | priorities: " ",.Q.a,.Q.A 26 | ``` 27 | 28 | It remains only to Find and sum their priorities. 29 | 30 | ```q 31 | sum priorities?err each inp 32 | ``` 33 | 34 | ## Part 2 35 | 36 | Divide the rucksacks into threes. 37 | 38 | ```q 39 | groups: {_[;x]where count[x]#100b} inp / group in threes 40 | ``` 41 | 42 | Use `{x where x in y}/` to return the only common item from the three lists. 43 | Prioritise as before. 44 | 45 | ```q 46 | badge: first ({x where x in y}/) :: / identify badge 47 | sum priorities?badge each groups 48 | ``` 49 | 50 | ## Refactor 51 | 52 | First we notice that `x where x in y` is actually `inter` and both parts of the problem use it: Part 1 between the rucksack halves, and Part 2 between the rucksacks in a group. 53 | 54 | So `first@inter/` works on either the two halves of a rucksack, or a group of rucksacks. 55 | 56 | Next we see we can replace `(" ",.Q.a,.Q.A)?` with `1+.Q.an?` 57 | 58 | We compose a function that iterates over lists of rucksack halves, or groups of rucksacks. 59 | 60 | ```q 61 | f:sum 1+ .Q.an? (first@inter/)each 62 | ``` 63 | 64 | The Take operator with null arguments will partition the rucksacks either: 65 | 66 | ```q 67 | 2 0N#/: inp / into halves 68 | 0N 3# inp / into threes 69 | ``` 70 | 71 | The complete solution: 72 | 73 | ```q 74 | f: sum 1+ .Q.an? (first@inter/)each 75 | f 2 0N#/: inp / part 1 76 | f 0N 3# inp / part 2 77 | ``` 78 | 79 | Or for both parts: 80 | 81 | ```q 82 | sum each 1+.Q.an?(first@inter/)each'(2 0N#/:;0N 3#)@\:inp 83 | ``` 84 | 85 | ## Contributors 86 | 87 | * András Dőtsch 88 | * Ajay Rathore 89 | * Cillian Reilly 90 | * Stephen Taylor 91 | 92 | -------------------------------------------------------------------------------- /aoc/2022/04.md: -------------------------------------------------------------------------------- 1 | # Day 4: Camp Cleanup 2 | 3 | > Space needs to be cleared before the last supplies can be unloaded from the ships, and so several Elves have been assigned the job of cleaning up sections of the camp. Every section has a unique ID number, and each Elf is assigned a range of section IDs. 4 | 5 | Advent of Code 2022 [Day 4](https://adventofcode.com/2022/day/4) 6 | 7 | ## Ingestion 8 | 9 | ```q 10 | q)show inp: read0`:test/04.txt /assignments 11 | "2-4,6-8" 12 | "2-3,4-5" 13 | "5-7,7-9" 14 | "2-8,3-7" 15 | "6-6,4-6" 16 | "2-6,4-8" 17 | ``` 18 | 19 | 20 | ## Part 1 21 | 22 | Parse the assignments into a list of 2×2 matrices: each one a pair of ranges. 23 | 24 | ```q 25 | q)show ass: "J"$''"-"vs''","vs' inp 26 | 2 4 6 8 27 | 2 3 4 5 28 | 5 7 7 9 29 | 2 8 3 7 30 | 6 6 4 6 31 | 2 6 4 8 32 | q)ass 3 33 | 2 8 34 | 3 7 35 | ``` 36 | 37 | Keyword `within` tests the first range against the second. 38 | 39 | ```q 40 | q).[within] ass 3 41 | 00b 42 | ``` 43 | 44 | Both have to be true to qualify. 45 | 46 | ```q 47 | q)all .[within] ass 3 48 | 0b 49 | ``` 50 | 51 | But we also need to test the second range against the first. 52 | We can use `reverse\` to get both the pairs and their reverse. 53 | 54 | ```q 55 | q)(reverse\) ass 3 56 | 2 8 3 7 57 | 3 7 2 8 58 | ``` 59 | 60 | So we can `reverse\` each assignment and test the assignments and their reverses. 61 | 62 | ```q 63 | q)((all .[within]::)'') (reverse\') ass 64 | 00b 65 | 00b 66 | 00b 67 | 01b 68 | 10b 69 | 00b 70 | 71 | q)sum any each((all .[within]::)'') (reverse\') ass 72 | 2i 73 | ``` 74 | 75 | ## Part 2 76 | 77 | The test for Part 2 is slightly different. 78 | Where we used `all` to test whether one range was wholly contained, we can use `any` to find if they overlap. 79 | 80 | ```q 81 | q)sum any each ((any .[within]::)'') (reverse\') ass 82 | 4i 83 | ``` 84 | 85 | ## Refactor 86 | 87 | The similar solutions suggest a refactoring to defer application of `all` and `any`. 88 | 89 | Use Each Each to apply `within .` to every assignmant and its reverse. 90 | 91 | ```q 92 | q)(.[within]'') (reverse\') ass 93 | 00b 00b 94 | 00b 00b 95 | 01b 10b 96 | 00b 11b 97 | 11b 01b 98 | 01b 10b 99 | 100 | q)(sum') (any'') (all'';any'')@\: (.[within]'') (reverse\') ass 101 | 2 4i 102 | ``` 103 | 104 | ## Alternatives 105 | 106 | There are other ways than `within` to test containment and overlap. 107 | 108 | Parse the assignments into a 2×2×N array. 109 | 110 | ```q 111 | q)i: ("jj";"-")0:/:("**";",")0:`:test/04.txt 112 | q)i 0 113 | 2 2 5 2 6 2 114 | 4 3 7 8 6 6 115 | q)i 1 116 | 6 4 7 3 4 4 117 | 8 5 9 7 6 8 118 | q)sum {0>=.[*]x-y} . i 119 | 2i 120 | q)sum {0>=.[*]x-reverse y} . i 121 | 4i 122 | ``` 123 | 124 | Or, sorting each matrix simplifies the range tests: 125 | 126 | ```q 127 | d4:{asc each "J"$"-"vs/:/:","vs/:x} 128 | {a:d4 x;sum(a[;1;1]<=a[;0;1]) or a[;0;0]=a[;1;0]} inp 129 | {a:d4 x;sum a[;1;0]<=a[;0;1]} inp 130 | ``` 131 | 132 | ## Contributors 133 | 134 | * András Dőtsch 135 | * Péter Györök 136 | * Sujoy Rakshit 137 | * Cillian Reilly 138 | * Stephen Taylor 139 | 140 | -------------------------------------------------------------------------------- /aoc/2022/05.md: -------------------------------------------------------------------------------- 1 | # Day 5: Supply Stacks 2 | 3 | > The expedition can depart as soon as the final supplies have been unloaded from the ships. Supplies are stored in stacks of marked crates, but because the needed supplies are buried under many other crates, the crates need to be rearranged. 4 | 5 | Advent of Code 2022 [Day 5](https://adventofcode.com/2022/day/5) 6 | 7 | ## Ingestion 8 | 9 | ```q 10 | inp: read0`:test/05.txt 11 | ``` 12 | 13 | Represent the stacks as a list of strings, top first, and the moves as a list of triples, with the stack indices using origin zero. 14 | 15 | ```q 16 | q)`s`m set'{ 17 | (trim@'flip x[;1+4*til(1+count first x)div 4]; /stacks 18 | flip 0 -1 -1+(" J J J";" ")0:y) /moves 19 | }. -1 1_'{(0,where not count each x)_ x} test 20 | `s`m 21 | 22 | q)s 23 | "NZ" 24 | "DCM" 25 | ,"P" 26 | 27 | q)m 28 | 1 1 0 29 | 3 0 2 30 | 2 1 0 31 | 1 0 1 32 | ``` 33 | 34 | ## Part 1 35 | 36 | We want a function `f` to apply one move from the list to the state and return the new state. 37 | The the final state will be `s f/m` and the answer to Part 1 will be `first each s f/m`. 38 | 39 | We can use Amend At to adjust the stacks in the state. 40 | 41 | ```q 42 | q){@[;y 2;(y[0]#x y 1),] x}[s] 1 1 0 /copy 1 from 1 to 0 43 | "DNZ" 44 | "DCM" 45 | ,"P" 46 | 47 | q){@[;y 1;y[0]_] @[;y 2;(y[0]#x y 1),] x}[s] 1 1 0 /and remove copied crate 48 | "DNZ" 49 | "CM" 50 | ,"P" 51 | ``` 52 | 53 | We can condense the two Amend Ats with the Over accumulator. 54 | 55 | ```q 56 | q){@/[x; y 1 2; (y[0]_;(y[0]#x y 1),)]}[s] 1 1 0 57 | "DNZ" 58 | "CM" 59 | ,"P" 60 | ``` 61 | 62 | Not there yet, as we see if we move two crates rather than one. 63 | 64 | ```q 65 | q){@/[x; y 1 2; (y[0]_;(y[0]#x y 1),)]}[s] 2 1 0 66 | "DCNZ" 67 | ,"M" 68 | ,"P" 69 | ``` 70 | 71 | Stack 0 should have been `CDNZ` had the crates been moved one at a time. 72 | We need to reverse the order of the crates being moved. 73 | 74 | ```q 75 | q){@/[x; y 1 2; (y[0]_;(reverse y[0]#x y 1),)]}[s] 2 1 0 76 | "CDNZ" 77 | ,"M" 78 | ,"P" 79 | ``` 80 | 81 | We have an `f`. Now we use Over to iterate it through the moves. 82 | 83 | ```q 84 | q)f: {@/[x; y 1 2; (y[0]_;(reverse y[0]#x y 1),)]} 85 | q)first each s f/m 86 | "CMZ" 87 | ``` 88 | 89 | ## Part 2 90 | 91 | Part 2 requires us only to omit the `reverse`. 92 | We can conveniently add a function argument to `f` and project it on either `reverse` or Identity. 93 | 94 | ```q 95 | q)f: {[o;s;m] @/[s;m 1 2;(m[0]_;(o m[0]#s m 1),)]} 96 | q)first each s f[reverse]/m 97 | "CMZ" 98 | q)first each s f[::]/m 99 | "MCD" 100 | ``` 101 | 102 | ## Animation 103 | 104 | For each move: clear the console by writing a Form Feed. 105 | Read the console height. 106 | Pad the stacks and set them upright; bracket each crate; write to the console with line breaks. Pause for half a second. 107 | 108 | ```q 109 | animate: {1 "\033[H\033[J"; /clear console 110 | ht: 7h$first system"c"; /console height 111 | -1 raze each ({$[null x;3#" ";"[",x,"]"]}'') 112 | reverse flip ht$reverse each x; 113 | system "sleep 0.5"; /pause 114 | x } 115 | s (animate@f[reverse]::)/m; 116 | ``` 117 | 118 | ![Animation of example](img/crates.gif) 119 | 120 | ## Contributors 121 | 122 | * András Dőtsch 123 | * Cillian Reilly 124 | * Stephen Taylor 125 | 126 | 127 | -------------------------------------------------------------------------------- /aoc/2022/06.md: -------------------------------------------------------------------------------- 1 | # Day 6: Tuning Trouble 2 | 3 | > The preparations are finally complete; you and the Elves leave camp on foot and begin to make your way toward the star fruit grove. 4 | > 5 | > As you move through the dense undergrowth, one of the Elves gives you a handheld device. He says that it has many fancy features, but the most important one to set up right now is the communication system. 6 | 7 | 8 | Advent of Code 2022 [Day 6](https://adventofcode.com/2022/day/6) 9 | 10 | ## Ingestion 11 | 12 | ```q 13 | input:read0`:test/06.txt 14 | ``` 15 | 16 | ## Part 1 17 | 18 | Looking for the marker, we have two things to do: 19 | 20 | 1. test a substring for no duplicate chars 21 | 1. either generate all the substrings or crawl the string testing for a marker 22 | 23 | ### Testing for a marker 24 | 25 | A simple way to test a substring for being a marker is `4=count distinct::`. 26 | We can make this independent of the substring length, as `{count[x]=count distinct x}`, or refactor the two `count`s out as `{.[=](count')1 distinct\x}`. 27 | 28 | At which point we notice we can drop the `count`s and simply use Match: `{x~distinct x}`. 29 | 30 | ```q 31 | q){4=count distinct x}each("abac";"abcd") 32 | 01b 33 | q){x~distinct x}each("abac";"abcd") 34 | 01b 35 | ``` 36 | 37 | But as `count` is close to free, there is no significant efficiency gain. 38 | 39 | ```q 40 | q)\ts:10000 {4=count distinct x}each("abac";"abcd") 41 | 10 1888 42 | q)\ts:10000 {x~distinct x}each("abac";"abcd") 43 | 10 1584 44 | ``` 45 | 46 | ### Finding substrings 47 | 48 | One way is to generate indices for all the 4-char substrings. 49 | 50 | ```q 51 | q)(til count[inp]-1)+\:til 4 52 | 0 1 2 3 53 | 1 2 3 4 54 | 2 3 4 5 55 | 3 4 5 6 56 | .. 57 | q)inp (til count[inp]-1)+\:til 4 58 | "mjqj" 59 | "jqjp" 60 | "qjpq" 61 | "jpqm" 62 | .. 63 | ``` 64 | 65 | Or just dropping a char and applying `4#`. 66 | 67 | ```q 68 | q)(1_)\[inp] 69 | "mjqjpqmgbljsphdztnvjfqwrcgsmlb" 70 | "jqjpqmgbljsphdztnvjfqwrcgsmlb" 71 | "qjpqmgbljsphdztnvjfqwrcgsmlb" 72 | "jpqmgbljsphdztnvjfqwrcgsmlb" 73 | .. 74 | q)4#'(1_)\[inp] 75 | "mjqj" 76 | "jqjp" 77 | "qjpq" 78 | "jpqm" 79 | .. 80 | ``` 81 | 82 | Or apply `next` three times, and flip. 83 | 84 | ```q 85 | q)3 next\inp 86 | "mjqjpqmgbljsphdztnvjfqwrcgsmlb" 87 | "jqjpqmgbljsphdztnvjfqwrcgsmlb " 88 | "qjpqmgbljsphdztnvjfqwrcgsmlb " 89 | "jpqmgbljsphdztnvjfqwrcgsmlb " 90 | q)flip 3 next\inp 91 | "mjqj" 92 | "jqjp" 93 | "qjpq" 94 | "jpqm" 95 | .. 96 | ``` 97 | 98 | Or 99 | 100 | ```q 101 | q){neg[y] sublist x,z}\[();4;inp] 102 | ,"m" 103 | "mj" 104 | "mjq" 105 | "mjqj" 106 | "jqjp" 107 | .. 108 | ``` 109 | 110 | It appears the third is the most efficient: 111 | 112 | ```q 113 | q)\ts:10000 inp (til count[inp]-1)+\:til 4 114 | 49 4000 115 | q)\ts:10000 (1_)\[inp] 116 | 52 2432 117 | q)\ts:10000 flip 3 next\inp 118 | 25 1792 119 | q)\ts:10000 {neg[y] sublist x,z}\[();4;inp] 120 | 254 2128 121 | ``` 122 | 123 | 124 | ## Applying the test 125 | 126 | We have a choice: 127 | 128 | 1. test all the substrings then look for the first hit 129 | 1. test each substring in turn until we find a hit 130 | 131 | ```q 132 | q)4+first where{x~distinct x}each flip 3 next\inp /test all 133 | 7 134 | q)4+first {x>count distinct y z}[4;inp](1+)/til 4 135 | 7 136 | ``` 137 | 138 | The second looks more efficient. It avoids many unnecessary tests when the marker occurs early in the string. 139 | But vector-hungry q sometimes makes ‘overcomputing’ faster. 140 | 141 | ```q 142 | q)\ts:10000 4+first where{x~distinct x}each flip 3 next\inp 143 | 111 3680 144 | q)\ts:10000 4+first {x>count distinct y z}[4;inp](1+)/til 4 145 | 29 2576 146 | ``` 147 | 148 | Not here: early termination of the search pays off. 149 | 150 | ## Part 2 151 | 152 | As we have been wise enough to consider the marker length as an argument, we can easily adapt the search. 153 | 154 | ```q 155 | q)4 14 {x+first {x>count distinct y z}[x;y](1+)/til x}\: inp 156 | 7 19 157 | ``` 158 | 159 | ## Contributors 160 | 161 | * Sean Ang 162 | * András Dőtsch 163 | * Tom Ferguson 164 | * Péter Györök 165 | * Nick Psaris 166 | * Cillian Reilly 167 | * Nathan Swann 168 | * Stephen Taylor 169 | * Zsolt Venczel 170 | 171 | -------------------------------------------------------------------------------- /aoc/2022/09.md: -------------------------------------------------------------------------------- 1 | # Day 9: Rope Bridge 2 | 3 | > This rope bridge creaks as you walk along it. You aren't sure how old it is, or whether it can even support your weight. It seems to support the Elves just fine, though. The bridge spans a gorge which was carved out by the massive river far below you. 4 | > 5 | > You step carefully; as you do, the ropes stretch and twist. You decide to distract yourself by modeling rope physics; maybe you can even figure out where not to step. 6 | 7 | Advent of Code 2022 [Day 9](https://adventofcode.com/2022/day/9) 8 | 9 | 10 | ## Ingestion 11 | 12 | ```q 13 | inp: read0 `:test/09.txt 14 | ``` 15 | 16 | ## Head positions 17 | 18 | Any move of the rope’s head by one space might require a move of the tail. 19 | So, while it would be easy to move the head several spaces each time, we shall interpret e.g. `R 4` as four moves to the right, and take cumulative sums to get the head positions. 20 | 21 | ```q 22 | q)show s: sums("RLDU"!(1 0;-1 0;0 -1;0 1))where .[!] ("CJ";" ")0:inp 23 | 1 0 24 | 2 0 25 | 3 0 26 | 4 0 27 | 4 1 28 | 4 2 29 | .. 30 | ``` 31 | 32 | Notice above how Apply Dict makes a dictionary of the two vectors returned by [Load CSV](https://code.kx.com/q/ref/file-text/#load-csv), which is then passed to `where`. 33 | You will be familiar with `where` on a boolean vector. 34 | 35 | ```q 36 | q)where 101b 37 | 0 2 38 | ``` 39 | 40 | You may also have seen that the rule for `where` extends to integers: instead of returning either one or zero copies of each index, it returns the specified number. 41 | 42 | ```q 43 | q)where 3 0 4 44 | 0 0 0 2 2 2 2 45 | ``` 46 | 47 | The same rule works also for dictionaries. 48 | 49 | ```q 50 | q)where `cow`sheep`cat!2 0 3 51 | `cow`cow`cat`cat`cat 52 | ``` 53 | 54 | In each case, `where` returns copies of its argument’s indices: the indices of a vector `v` are `til v`; of a dictionary `d`, they are `key d`. 55 | 56 | 57 | ## Tail positions 58 | 59 | The tail starts from the same position as the head: `0 0`. 60 | At each new head position we decide whether to adjust the position of the tail. 61 | 62 | ```q 63 | move: {$[1 You avoid the ropes, plunge into the river, and swim to shore. 4 | > 5 | > The Elves yell something about meeting back up with them upriver, but the river is too loud to tell exactly what they're saying. They finish crossing the bridge and disappear from view. 6 | > 7 | > Situations like this must be why the Elves prioritized getting the communication system on your handheld device working. You pull it out of your pack, but the amount of water slowly draining from a big crack in its screen tells you it probably won't be of much immediate use. 8 | 9 | Advent of Code 2022 [Day 10](https://adventofcode.com/2022/day/10) 10 | 11 | 12 | ## Ingestion 13 | 14 | ```q 15 | q)show inp: read0 `:test/10.txt 16 | q)inp 17 | "addx 15" 18 | "addx -11" 19 | "addx 6" 20 | "addx -3" 21 | "addx 5" 22 | "addx -1" 23 | "addx -8" 24 | "addx 13" 25 | "addx 4" 26 | "noop" 27 | "addx -1" 28 | .. 29 | ``` 30 | 31 | ## Part 1 32 | 33 | The `noop` operation completes in a single cycle; the `addx` in two, with the X register incrementing on the second. 34 | 35 | If we replace both commands with zeros we have the series of changes to the X register; cumulative sums give the series of X-register values. 36 | 37 | ```q 38 | q)show i:1+\get ssr/[;("addx";"noop");"0"]" "sv inp 39 | 1 16 16 5 5 11 11 8 8 13 13 12 12 4 4 17 17 21 21 21 20 20 25 25 24 24 29 29 28 28 33 33 32 32 37 37 36 36 1 1 2 .. 40 | ``` 41 | 42 | Or we can use the q interpreter itself. 43 | 44 | ```q 45 | q)noop:0;addx:0, 46 | q)show i:1+\get","sv inp 47 | 1 16 16 5 5 11 11 8 8 13 13 12 12 4 4 17 17 21 21 21 20 20 25 25 24 24 29 29 28 28 33 33 32 32 37 37 36 36 1 1 2 .. 48 | ``` 49 | 50 | It remains only to index into the specified cycles. 51 | 52 | ```q 53 | q)show c:20+40*til 6 /cycles 54 | 20 60 100 140 180 220 55 | q)i c-2 /values at start of cycles 56 | 21 19 18 21 16 18 57 | q)sum i[c-2]*c:20+40*til 6 /part 1 58 | 13140 59 | ``` 60 | 61 | ## Part 2 62 | 63 | The horizontal pixel co-ords of a 6×40 screen: 64 | ``` 65 | q)240#til 40 66 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 0 1.. 67 | ``` 68 | 69 | The pixels of `i` that light up: 70 | 71 | ```q 72 | q)(240#til 40)within'-1 1+/:0^prev i 73 | 11001100110011001100110011001100110011001110001110001110001110001110001110001110111100001111000011110000111100001.. 74 | ``` 75 | 76 | Or: 77 | 78 | ```q 79 | q)2>abs(-1_1,i)-240#til 40 80 | 11001100110011001100110011001100110011001110001110001110001110001110001110001110111100001111000011110000111100001.. 81 | 82 | q)show".#"40 cut 2>abs(-1_1,i)-240#til 40 83 | "##..##..##..##..##..##..##..##..##..##.." 84 | "###...###...###...###...###...###...###." 85 | "####....####....####....####....####...." 86 | "#####.....#####.....#####.....#####....." 87 | "######......######......######......####" 88 | "#######.......#######.......#######....." 89 | ``` 90 | 91 | The puzzle input will produce recognizable characters on the CRT. 92 | 93 | ```q 94 | .d10.ocr:()!(); 95 | .d10.ocr[529680320]: "A" 96 | .d10.ocr[1067881856]: "B" 97 | .d10.ocr[512103552]: "C" 98 | .. 99 | 100 | .d10.ocr 2 sv/:raze each 5 cut flip 40 cut 2>abs(-1_1,i)-240#til 40 101 | ``` 102 | 103 | ## Solutions 104 | 105 | ```q 106 | i:1+\get ssr/[;("addx";"noop");"0"]" "sv inp /X-register values 107 | sum i[c-2]*c:20+40*til 6 /part 1 108 | show".#"40 cut 2>abs(-1_1,i)-240#til 40 /part 2 109 | ``` 110 | 111 | ## Contributors 112 | 113 | * András Dőtsch 114 | * Péter Györök 115 | * Cillian Reilly 116 | * Stephen Taylor 117 | * Zsolt Venczel 118 | -------------------------------------------------------------------------------- /aoc/2022/12.md: -------------------------------------------------------------------------------- 1 | # Day 12: Hill Climbing Algorithm 2 | 3 | > You try contacting the Elves using your handheld device, but the river you're following must be too low to get a decent signal. 4 | > 5 | > You ask the device for a heightmap of the surrounding area (your puzzle input). The heightmap shows the local area from above broken into a grid; the elevation of each square of the grid is given by a single lowercase letter, where a is the lowest elevation, b is the next-lowest, and so on up to the highest elevation, z. 6 | 7 | Advent of Code 2022 [Day 12](https://adventofcode.com/2022/day/12) 8 | 9 | 10 | ## Ingestion 11 | 12 | ```q 13 | q)show inp: read0 `:test/12.txt 14 | "Sabqponm" 15 | "abcryxxl" 16 | "accszExk" 17 | "acctuvwj" 18 | "abdefghi" 19 | ``` 20 | 21 | ## Part 1 22 | 23 | We can use the `vs` keyword to convert indices of a razed matrix into co-ordinate pairs. 24 | 25 | ```q 26 | q)show Shp:count each 1 first\inp /map shape 27 | 5 8 28 | q)Shp vs/:raze[inp]?"SE" 29 | 0 0 30 | 2 5 31 | q)`Start`End set'Shp vs/:raze[inp]?"SE"; /start & end coords 32 | ``` 33 | 34 | We shall need to consult a height map. 35 | 36 | ```q 37 | Map: ./[;(Start;End);:;0 25] -97+6h$inp /height map 38 | ``` 39 | 40 | Our strategy is a breadth-first search: start from the end point and with each step identify the unvisited accessible neighbours until they include the start point. 41 | The number of steps taken will be the length of the shortest route. 42 | 43 | We can represent the ongoing search as a pair of lists. 44 | The first is the points visited; the second a subset of it, the points last visited. 45 | 46 | ```q 47 | Is: 2 1 2#End /initial state 48 | ``` 49 | 50 | Each step extends the list of visited points. 51 | We mean to iterate until the start point shows up. 52 | 53 | ```q 54 | adj: (0 1;1 0;0 -1;-1 0)+\: /adjacent points 55 | filter: {y where not[null h] and (-2+Map . x)< h: Map ./:y} 56 | step: {(x,;::)@\:except[;x]distinct raze{filter[x] adj x}each y}. 57 | ``` 58 | 59 | The `adj` projection returns adjacent points, but some can be inaccessible: either off the map, or failing the height test. 60 | The `filter` function removes inaccessible points. 61 | When it has pruned the neighbours of each point last visited, the pruned lists are razed, any duplicates removed, and also any points already visited. 62 | 63 | The result is the extended list of visited points, and the points just now visited. 64 | 65 | The [While iterator](https://code.kx.com/q/ref/accumulators/#while) 66 | keeps taking steps until the starting point has been visited. 67 | It remains only to count the steps. 68 | 69 | 70 | ```q 71 | -1+count(not Start in last@) step\ Is /part 1 72 | ``` 73 | 74 | 75 | ## Part 2 76 | 77 | For Part 2 we need only replace the start point with a list of the points where the map shows an `"a"`. 78 | 79 | ```q 80 | a: Shp vs/:where raze inp="a" /"a" coords 81 | -1+count(not any a in last@) step\ Is /part 2 82 | ``` 83 | 84 | 85 | ## Observations 86 | 87 | The `vs` and `sv` keywords are best known for joining and partitioning lists. 88 | Less well known is their use for encoding and decoding numbers to different bases. 89 | For example, a billion seconds as years, days, hours and seconds: 90 | 91 | ```q 92 | q)1000 365 24 60 60 vs 1000000000 93 | 31 259 1 46 40 94 | ``` 95 | 96 | Using the Do form of Scan gets us the shape of the input matrix. 97 | 98 | ```q 99 | q)count each 1 first\inp 100 | 5 8 101 | ``` 102 | 103 | And that shape becomes the base by which we convert indices of the razed matrix into row-column indices. 104 | 105 | The adjacency function can generate invalid indices, but passed to `Map .` they become nulls we can filter out. 106 | 107 | 108 | ## Contributors 109 | 110 | * Cillian Reilly 111 | * Stephen Taylor 112 | 113 | -------------------------------------------------------------------------------- /aoc/2022/13.md: -------------------------------------------------------------------------------- 1 | # Day 13: Distress Signal 2 | 3 | > You climb the hill and again try contacting the Elves. However, you instead receive a signal you weren't expecting: a distress signal. 4 | > 5 | > Your handheld device must still not be working properly; the packets from the distress signal got decoded out of order. You'll need to re-order the list of received packets (your puzzle input) to decode the message. 6 | 7 | Advent of Code 2022 [Day 13](https://adventofcode.com/2022/day/13) 8 | 9 | 10 | ## Ingestion 11 | 12 | ```q 13 | q)show inp: read0 `:test/13.txt 14 | [1,1,3,1,1] 15 | [1,1,5,1,1] 16 | 17 | [[1],[2,3,4]] 18 | [[1],4] 19 | 20 | [9] 21 | [[8,7,6]] 22 | 23 | .. 24 | ``` 25 | 26 | The first job is to parse the strings into a list of signal pairs. 27 | 28 | > No need to write your own JSON parser if we have one built in. — Péter Györök 29 | 30 | ```q 31 | q) show I: 2 cut .j.k each inp where count[inp]#110b 32 | 1 1 3 1 1 1 1 5 1 1 33 | ,1f 2 3 4f ,1f 4f 34 | 9 8 7 6 35 | (4 4f;4f;4f) (4 4f;4f;4f;4f) 36 | 7 7 7 7f 7 7 7f 37 | () ,3f 38 | ``` 39 | 40 | 41 | ## Part 1 42 | 43 | Compare the signals in each pair, returning the ‘difference’ between each pair. 44 | 45 | Return a positive number if the left argument `x` is ‘greater’ than the right argument `y`; a zero if they are equal, otherwise a negative. 46 | 47 | 1. If `x` and `y` are both atoms, return their difference. 48 | 2. If one argument is an empty list, return the length of the other, negated if `y` is longer. 49 | 3. At least one argument is a list and neither is empty. Recurse on the first item of each. If there is a difference, return it; otherwise, drop the first item of each and recurse. 50 | 51 | ```q 52 | cmp:{ 53 | $[(0>type x)&0>type y; `long$x-y; 54 | (0=count x)|0=count y; count[x]-count y; 55 | r:cmp[first x;first y]; r; 56 | cmp[1_(),x;1_(),y] ] } 57 | ``` 58 | 59 | Notice in the last line how `(),` ensures the recursion is passed two lists. 60 | 61 | It remains only to apply `cmp` to each pair of signals and sum the (origin-1) indices of the negatives. 62 | 63 | 64 | ```q 65 | sum 1+where 1>cmp .' I /part 1 66 | ``` 67 | 68 | ## Part 2 69 | 70 | A sorting function `qs`: for each list argument with more than one item, use `cmp` to get the ‘difference’ between its item and the first item 71 | 72 | ```q 73 | r: x cmp\:first x 74 | ``` 75 | 76 | and return 77 | 78 | ```q 79 | qs[x where r<0],(x where r=0),qs x where r>0 80 | ``` 81 | 82 | But we do not need to examine `r` three times; `group signum` will do it for us. 83 | 84 | ```q 85 | raze(qs;::;qs)@'x(group signum x cmp\:first x)@-1 0 1 86 | ``` 87 | 88 | Moreover, `qs` does not need to know its own name: `.z.s` denotes the currently running function. 89 | 90 | ```q 91 | qs: {$[2>count x; x; 92 | raze(.z.s;::;.z.s)@'x(group signum x cmp\:first x)@-1 0 1 93 | ]} 94 | ``` 95 | 96 | Prepend lists corresponding to `[[2]]` and `[[6]]` to the razed signals, and sort. 97 | 98 | ```q 99 | A: .j.k"[[2]]"; B: .j.k"[[6]]"; 100 | J: qs(A;B),raze I 101 | ``` 102 | 103 | It remains only to find `A` and `B` in `J` and multiply the indices. 104 | 105 | ```q 106 | prd 1+(where A~/:J;where B~/:J) /part 2 107 | ``` 108 | 109 | ## With combinator 110 | 111 | Notice a recurring pattern, in which the same unary function is applied to both `x` and `y`. We can rewrite our solutions using a ‘both’ combinator. 112 | 113 | ```q 114 | I: 2 cut .j.k each inp where count[inp]#110b 115 | 116 | b: {x@/:(y;z)} / 'both' combinator 117 | 118 | cmp:{ 119 | $[all b[type;x;y]<0; `long$x-y; 120 | any b[count;x;y]=0; .[-] b[count;x;y]; 121 | r:cmp . b[first;x;y]; r; 122 | cmp . b[1_(),;x;y] ] } 123 | 124 | sum 1+where 1>cmp .' I /part 1 125 | 126 | qs: {$[2>count x; x; 127 | raze(.z.s;::;.z.s)@'x(group signum x cmp\:first x)@-1 0 1 128 | ]} 129 | 130 | `A`B set'b[.j.k;"[[2]]";"[[6]]"]; 131 | J: qs(A;B),raze I 132 | prd 1+b[where ~/:[;J]::; A; B] /part 2 133 | ``` 134 | 135 | 136 | ## Comments 137 | 138 | Using Find `?` in the last line, i.e. `J?(A;B)` would be a mistake, because Find is [type-specific](https://code.kx.com/q/ref/find/#type-specific). 139 | 140 | ```q 141 | q)A~/:J 142 | 000000000100000000b 143 | q)where A~/:J 144 | ,9 145 | q)J?A 146 | ,18 147 | q)A in J 148 | ,0b 149 | ``` 150 | 151 | Other ways to write the combinator: `{x each(y;z)}` or `{(x y;x z)}`. 152 | 153 | 154 | ## Contributors 155 | 156 | * András Dőtsch 157 | * Stephen Taylor 158 | 159 | 160 | -------------------------------------------------------------------------------- /aoc/2022/17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/aoc/2022/17.gif -------------------------------------------------------------------------------- /aoc/2022/img/crates.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/aoc/2022/img/crates.gif -------------------------------------------------------------------------------- /aoc/2022/input/06.txt: -------------------------------------------------------------------------------- 1 | qzbzwwghwhwdhdqhhbhfbfsstggdsssgzgdzzdbbbzmbzzvlldppjnjlltwtsszwswgssjnsjnnfqfzqqjzjfjmfmwfmfhfnnmdnmnllbzzlbzlzflldzdbzbsbdddpgdppzhphhjjtccjgcgrgjgcjgjjsbjbffsgsqqrsqqgppgmgcmmrdrqdqbqmmctchcgcdgdwdwcdcjcfjccmpmlpllqqpmpllhfhchppwwdmdhdphpvprrhwhgwwlrwlwggwlwqqnmqnqrrbbzdzwddqzznllzwlljsscqqtlltppqspswsttlrttnvvvwllfslsjsfjssnqnbbbvgvlltjtltjljmljjfgfbggcbgbmbjjvwjvjgvgzvvzddrjdddrwrlrlgldlhlwwcddbsbbtwwcssrnndvvsbsnbsbmbnmngnpgpphfhzhshllltqtppnrrzpzrpzzrttmbmssbrbmbsmsnspnsncscwwmjwmwdmwmrmvmqvqvjqvvnrrtntwwwwsrwrnwnrwwwlslrlhrllvpvhppdpprrgzrgzggqmqgmgvghhsmhhjljfflrflfrlrzzbjjqmmmcncddvhhzjjqzzjfzzbssjqqtsqtqccmttdhttmwtmtffspplhlrhrdhhhpghgrhrchhmgmqgqlglssvnnwrrrrqqbmmpgmpmdmmljlflzzjttqntqqcnqccrvcczffclffmvfvwvmvnvsvnvffczzljzztdtztcztctbtppmrprqprpbbhlhphphhvppvdvmddvcctvvjbvvpmpbpnpllvclvlqlwqqpcpffdwdsdttzftfddbrrgsrgsgvgpgjpggfvgfvvtqtnnscssmnnfqnnblnnjlnlbbjrrmmpgmgnnqbbcjbcjbbmjjljsjrsjrsrwrgwgpgqgccqppfdpdssffgdgwddcvdvzzpttjlttmwwhnnlntncttfvfwvvwrvrwwlhlwlvwvzvpvfpvvsbslblrlssjddwhwfhwffqjfjzfjfmfrrvsrrlbrrdfdmdwmddpnpfnpfnfppczpprzprpvpjjtltptvvrgvvsttflfvfqqhnnbmnbmmpsptpdpttrbbhjbbdnntppbsbmssgccfdfflppbcpbblclrlhrhttffvqqvvnpnmpnnrbnnhqnqrrwvwrrbvbffcvctcjcwwmzmvvtdvtvbtblbvlbvlvdvdrdsrdrprllnzznzhhcjjsgglfglgrlrwwfcfzfjzfztfztzggffjftjffcbfbhhwfwnnbssrpsppmllszstztwwgbwgbgtbgggztgztzwtztbbrffznndhdmmqggssjfssrgssbnsndnqnvqvqvjqvqttlctltvlttrzrqrrdprddpqqvppvddgmdddpldllnvvjdjcjdjvvznzqqbgqbgbpbnbvvdjvvsnndsdjjjhnhggrnnrvrvlvqllqhhsbhssvvlhlssgqgmqqcscpsspsrpsrpspvvdmvdvwwcjwwvhwvvmzvzvfvccfzczjccscbcrcjrrrsgrsspnsntsnnrnwwhdwwzhzbbwgwcgglvlttqrttvrrgprrljlddnttqrqffgdfgdgzzhghthhmdmsmtsshhsfhhgzgvzgzwzffvlffzjjrttsdddbldljlvjvjttwdwzzrbblwbbgmbmgmbggbdbsbqqwzzgnzgzczpzfztftbtwbtbsttrwrfrssbrrdqdjqdqppdsswrwttmgmllqbqnnpspjjzjjmbbsddgjgbjggqqlgqgmgdmmwcmwcmwwsddvgvpphmhqmmlvlpvlpltllphhcshhrsrgsgzssspjspplgghvvwhwgwssbhshvvscshhbccbtcbcvvmnndsdwwbzbffhmmbppfjppbsblbtlltggzczdczdzjdjpjtppwdwlwqwnwjnnvttmcmzzqccvfcvvmrmzmwmhmttgdgmsrlddnbgqfbbmrpdglpbtdqpmctzjrffvvqnltcqlfddwqhvjpzhczzwhsmjtrpgsdtqlcqsljsjzqwhcfwttgghsjqhzqlgjzgrtgttwblpprbppcpzsbntrwwmvfvbmjjrjwjqcjhnstmvwzrbnjpzznnctrtllzhtwttntjqwjnfspzccqpjlzbncgbjjjztbgfmzflzsqflflcrfhtlsgbdfdbtwwqfdrqhzmmqdqthwzwqqqzddfvbwhnqwqtgwhtzlqqpwhcjhglcmmncvfcmqdwnzzmjbflwjrcjzwcblftzrpdcjzcmtzccjbsqmcnfmbsmrvlhswnmrqdczvvzzcnffgljdbtlvjgrqttcjhjmcdllnvhcdpztqghfgvjcqmqvmdwhcgrtwpjlmjfbqmnjnbvvjczcwfcrhcgzmsvmjlplcpghnqtpzddnwtmrwmqwbttsnlngszfbnslqvlbzbfzqnjpdvcdpmjpmmjhvzwwgzfjfqwbqwrznhsdpjgsvzlsrtlmhjrfnwrmljlqzwnfnsmqtzfsldwrgmbrrvcmmmdmwflwnvpwsrrstmffwbtwqmjzdnzbwmqfrfdgsmhzhprdsgsqtljqhtdqmvnzlwhrrqqftbvnhmjnzvmbdqpjhzjnszgcfptfcmthpfcvfvdmwdswzfgwjblglfbpfvvwrmnzlcvtgqbcrhfqlffrznnhbtbwdwdldthbhdsqvnghpqdlvpfmzhjbtdhfmrdzpghtppmvddnphcnnczvznwzrvtcwvpslhrhmhzbzqtjqjvdpwncjbqdnwwpnfblqtqdwwqncbvtsncfhgncrprvhvzppwjfpdmtdrmtfcqdmdhwzrhpnrvspfbzhsvlpwzgrrhnrllhmpcdfcqdhcnphlffpbfmbsznmvfdgshbsjcjjvhqqfpmjgpdpcrglbqdrnqmftqtnwcsgqzdwntfplsnlhdbdmcgwfldzzgmzjsdnldbnlnhjqhpmnsljsbhrglhjbbrmlhrmjnvzhnlvnfpdzfzwwdpzwhnqhlbqhrgfmvzpctdvscqbgznzdsvvvvcjnmbzlvsptslmqnggqjcmgvtgbnrzlmzqzmtdfvhjqqcpvbngmngjvrtcfvsmbvthvhmdcfhthmnjcvsvmsbwsjtmrwshspcsmnhvzqvglntngbmgtdngbvvcjrznpdmmsssljnnqjwwfzgwtlfqqpsqghjgrghldrcdmcqvqdjsfrfrnlnvltpfjhmcclwbsdcbmvmlnwltztfggzmrtnsczwvqgpqtwffmphprgrmjlnftlgqjvrngbcndlmrblmvcjsdhdcmtgsztjttpbgcznfcgdwfwdnqmrrjgdgrgshjfjqrbsjdhblvrqhlfphnbdslrjszcnpfhhwrfhhdvqbjpsmzznzbtbsgcggtctfbsrscvzlplfhlwjlrmzhbwjqhffdhrwcdctwvttwqzbdtrhdhdvtgvdbzjtqvdgbpwtzqqqnljztgpbjjcrgdgmrrsfvngcdbgzvcfpdppbgfrmmdnqdvtlwwglmghjwfjjrwjfnwgwdplbmlfljhsmshwvvvtdnvfcbbwplwnvzfcjwgsrrlctpsrhprttcjgcmfsjggfvbbljsbjtzplvjdwnwgsgvvntjwdwdqbwmtnnlgdcmfcccnwnrjlqtznjhdzwfpbzhjdmwwpcmffcwsnpfhmgqgwwnvpmqvrdfhlqtghrrbggdmtvpqgqsspmchnrqnrmqlddnspcdrwqpvclhrvjtzhpvthpltwqqbrdfjtnwncwrmdqszdpmmdzmjwjvqnfszvbchfdvwzhtrfgfhfmgwprdpqgmbfntsqztvqmtjvgbsjvzsbhfznbbzrstqbrrmqdjcztmfpnwbmvtccmvlhtvmgfdzcchbccrzznscbdwrdtnpslvcqmgrrvwhnjgjdpvbfgsdtdcmhpnwfwnnntqjqnwzfwnhsrjbhtqtlncvsnhgvtntfwldqfzztcdctsscfdmtnmdqgqgwmtqhlmswtqrvqbchdwtjsdlqjvfjdtmzlvrzwvfprzvjzrrfn 2 | -------------------------------------------------------------------------------- /aoc/2022/input/10.txt: -------------------------------------------------------------------------------- 1 | noop 2 | noop 3 | noop 4 | addx 3 5 | addx 7 6 | noop 7 | noop 8 | noop 9 | noop 10 | addx 6 11 | noop 12 | addx -1 13 | noop 14 | addx 5 15 | addx 1 16 | noop 17 | addx 4 18 | noop 19 | noop 20 | noop 21 | noop 22 | addx 6 23 | addx -1 24 | noop 25 | addx 3 26 | addx -13 27 | addx -22 28 | noop 29 | noop 30 | addx 3 31 | addx 2 32 | addx 11 33 | addx -4 34 | addx 11 35 | addx -10 36 | addx 2 37 | addx 5 38 | addx 2 39 | addx -2 40 | noop 41 | addx 7 42 | addx 3 43 | addx -2 44 | addx 2 45 | addx 5 46 | addx 2 47 | addx -2 48 | addx -8 49 | addx -27 50 | addx 5 51 | addx 2 52 | addx 21 53 | addx -21 54 | addx 3 55 | addx 5 56 | addx 2 57 | addx -3 58 | addx 4 59 | addx 3 60 | addx 1 61 | addx 5 62 | noop 63 | noop 64 | noop 65 | noop 66 | addx 3 67 | addx 1 68 | addx 6 69 | addx -31 70 | noop 71 | addx -4 72 | noop 73 | noop 74 | noop 75 | noop 76 | addx 3 77 | addx 7 78 | noop 79 | addx -1 80 | addx 1 81 | addx 5 82 | noop 83 | addx 1 84 | noop 85 | addx 2 86 | addx -8 87 | addx 15 88 | addx 3 89 | noop 90 | addx 2 91 | addx 5 92 | noop 93 | noop 94 | noop 95 | addx -28 96 | addx 11 97 | addx -20 98 | noop 99 | addx 7 100 | addx -2 101 | addx 7 102 | noop 103 | addx -2 104 | noop 105 | addx -6 106 | addx 11 107 | noop 108 | addx 3 109 | addx 2 110 | noop 111 | noop 112 | addx 7 113 | addx 3 114 | addx -2 115 | addx 2 116 | addx 5 117 | addx 2 118 | addx -16 119 | addx -10 120 | addx -11 121 | addx 27 122 | addx -20 123 | noop 124 | addx 2 125 | addx 3 126 | addx 5 127 | noop 128 | noop 129 | noop 130 | addx 3 131 | addx -2 132 | addx 2 133 | noop 134 | addx -14 135 | addx 21 136 | noop 137 | addx -6 138 | addx 12 139 | noop 140 | addx -21 141 | addx 24 142 | addx 2 143 | noop 144 | noop 145 | noop 146 | -------------------------------------------------------------------------------- /aoc/2022/input/11.txt: -------------------------------------------------------------------------------- 1 | Monkey 0: 2 | Starting items: 91, 58, 52, 69, 95, 54 3 | Operation: new = old * 13 4 | Test: divisible by 7 5 | If true: throw to monkey 1 6 | If false: throw to monkey 5 7 | 8 | Monkey 1: 9 | Starting items: 80, 80, 97, 84 10 | Operation: new = old * old 11 | Test: divisible by 3 12 | If true: throw to monkey 3 13 | If false: throw to monkey 5 14 | 15 | Monkey 2: 16 | Starting items: 86, 92, 71 17 | Operation: new = old + 7 18 | Test: divisible by 2 19 | If true: throw to monkey 0 20 | If false: throw to monkey 4 21 | 22 | Monkey 3: 23 | Starting items: 96, 90, 99, 76, 79, 85, 98, 61 24 | Operation: new = old + 4 25 | Test: divisible by 11 26 | If true: throw to monkey 7 27 | If false: throw to monkey 6 28 | 29 | Monkey 4: 30 | Starting items: 60, 83, 68, 64, 73 31 | Operation: new = old * 19 32 | Test: divisible by 17 33 | If true: throw to monkey 1 34 | If false: throw to monkey 0 35 | 36 | Monkey 5: 37 | Starting items: 96, 52, 52, 94, 76, 51, 57 38 | Operation: new = old + 3 39 | Test: divisible by 5 40 | If true: throw to monkey 7 41 | If false: throw to monkey 3 42 | 43 | Monkey 6: 44 | Starting items: 75 45 | Operation: new = old + 5 46 | Test: divisible by 13 47 | If true: throw to monkey 4 48 | If false: throw to monkey 2 49 | 50 | Monkey 7: 51 | Starting items: 83, 75 52 | Operation: new = old + 1 53 | Test: divisible by 19 54 | If true: throw to monkey 2 55 | If false: throw to monkey 6 -------------------------------------------------------------------------------- /aoc/2022/input/15.txt: -------------------------------------------------------------------------------- 1 | Sensor at x=1384790, y=3850432: closest beacon is at x=2674241, y=4192888 2 | Sensor at x=2825953, y=288046: closest beacon is at x=2154954, y=-342775 3 | Sensor at x=3553843, y=2822363: closest beacon is at x=3444765, y=2347460 4 | Sensor at x=2495377, y=3130491: closest beacon is at x=2761496, y=2831113 5 | Sensor at x=1329263, y=1778185: closest beacon is at x=2729595, y=2000000 6 | Sensor at x=2882039, y=2206085: closest beacon is at x=2729595, y=2000000 7 | Sensor at x=3903141, y=2510440: closest beacon is at x=4006219, y=3011198 8 | Sensor at x=3403454, y=3996578: closest beacon is at x=3754119, y=4475047 9 | Sensor at x=3630476, y=1048796: closest beacon is at x=3444765, y=2347460 10 | Sensor at x=16252, y=2089672: closest beacon is at x=-276514, y=2995794 11 | Sensor at x=428672, y=1150723: closest beacon is at x=-281319, y=668868 12 | Sensor at x=2939101, y=3624676: closest beacon is at x=2674241, y=4192888 13 | Sensor at x=3166958, y=2890076: closest beacon is at x=2761496, y=2831113 14 | Sensor at x=3758241, y=3546895: closest beacon is at x=4006219, y=3011198 15 | Sensor at x=218942, y=3011070: closest beacon is at x=-276514, y=2995794 16 | Sensor at x=52656, y=3484635: closest beacon is at x=-276514, y=2995794 17 | Sensor at x=2057106, y=405314: closest beacon is at x=2154954, y=-342775 18 | Sensor at x=1966905, y=2495701: closest beacon is at x=2761496, y=2831113 19 | Sensor at x=511976, y=2696731: closest beacon is at x=-276514, y=2995794 20 | Sensor at x=3094465, y=2478570: closest beacon is at x=3444765, y=2347460 21 | Sensor at x=806671, y=228252: closest beacon is at x=-281319, y=668868 22 | Sensor at x=3011731, y=1976307: closest beacon is at x=2729595, y=2000000 23 | -------------------------------------------------------------------------------- /aoc/2022/input/16.txt: -------------------------------------------------------------------------------- 1 | Valve OA has flow rate=0; tunnels lead to valves VP, VM 2 | Valve GA has flow rate=13; tunnel leads to valve KV 3 | Valve WD has flow rate=0; tunnels lead to valves SH, XQ 4 | Valve TE has flow rate=0; tunnels lead to valves OY, DO 5 | Valve JR has flow rate=0; tunnels lead to valves TR, LY 6 | Valve JQ has flow rate=0; tunnels lead to valves TD, DZ 7 | Valve VH has flow rate=6; tunnels lead to valves WY, YQ, NU 8 | Valve NX has flow rate=0; tunnels lead to valves XQ, MN 9 | Valve XL has flow rate=0; tunnels lead to valves AA, FA 10 | Valve QY has flow rate=0; tunnels lead to valves NU, DO 11 | Valve KV has flow rate=0; tunnels lead to valves GA, XQ 12 | Valve NK has flow rate=0; tunnels lead to valves XW, XQ 13 | Valve JU has flow rate=0; tunnels lead to valves QH, TB 14 | Valve XZ has flow rate=0; tunnels lead to valves AA, SH 15 | Valve XQ has flow rate=18; tunnels lead to valves GK, NX, WD, KV, NK 16 | Valve VM has flow rate=19; tunnels lead to valves LY, OA, OY, AE 17 | Valve LE has flow rate=0; tunnels lead to valves MN, NS 18 | Valve HO has flow rate=0; tunnels lead to valves GO, QH 19 | Valve PX has flow rate=0; tunnels lead to valves MN, VP 20 | Valve MN has flow rate=4; tunnels lead to valves LE, UX, TB, NX, PX 21 | Valve VB has flow rate=0; tunnels lead to valves XM, AA 22 | Valve VP has flow rate=21; tunnels lead to valves XM, WT, BG, PX, OA 23 | Valve KI has flow rate=15; tunnels lead to valves XU, MT 24 | Valve NU has flow rate=0; tunnels lead to valves QY, VH 25 | Valve WT has flow rate=0; tunnels lead to valves SH, VP 26 | Valve OY has flow rate=0; tunnels lead to valves VM, TE 27 | Valve VS has flow rate=0; tunnels lead to valves QH, SH 28 | Valve XM has flow rate=0; tunnels lead to valves VB, VP 29 | Valve HI has flow rate=17; tunnel leads to valve TD 30 | Valve TB has flow rate=0; tunnels lead to valves JU, MN 31 | Valve BG has flow rate=0; tunnels lead to valves VP, GK 32 | Valve HN has flow rate=16; tunnel leads to valve BO 33 | Valve MT has flow rate=0; tunnels lead to valves KI, BO 34 | Valve OX has flow rate=0; tunnels lead to valves DZ, ZF 35 | Valve QH has flow rate=5; tunnels lead to valves FA, DW, VS, JU, HO 36 | Valve YQ has flow rate=0; tunnels lead to valves VH, AE 37 | Valve DW has flow rate=0; tunnels lead to valves ML, QH 38 | Valve WY has flow rate=0; tunnels lead to valves HS, VH 39 | Valve GO has flow rate=0; tunnels lead to valves HO, DO 40 | Valve UX has flow rate=0; tunnels lead to valves AA, MN 41 | Valve AE has flow rate=0; tunnels lead to valves YQ, VM 42 | Valve DZ has flow rate=9; tunnels lead to valves HS, OX, JQ 43 | Valve NS has flow rate=0; tunnels lead to valves SH, LE 44 | Valve LY has flow rate=0; tunnels lead to valves JR, VM 45 | Valve BO has flow rate=0; tunnels lead to valves HN, MT 46 | Valve HS has flow rate=0; tunnels lead to valves WY, DZ 47 | Valve XW has flow rate=0; tunnels lead to valves NK, AA 48 | Valve DO has flow rate=11; tunnels lead to valves TE, XU, ZF, QY, GO 49 | Valve FA has flow rate=0; tunnels lead to valves XL, QH 50 | Valve AA has flow rate=0; tunnels lead to valves VB, XL, XZ, XW, UX 51 | Valve VW has flow rate=14; tunnel leads to valve ML 52 | Valve SH has flow rate=8; tunnels lead to valves NS, WT, XZ, VS, WD 53 | Valve XU has flow rate=0; tunnels lead to valves DO, KI 54 | Valve ZF has flow rate=0; tunnels lead to valves OX, DO 55 | Valve GK has flow rate=0; tunnels lead to valves XQ, BG 56 | Valve ML has flow rate=0; tunnels lead to valves VW, DW 57 | Valve TD has flow rate=0; tunnels lead to valves HI, JQ 58 | Valve TR has flow rate=25; tunnel leads to valve JR 59 | -------------------------------------------------------------------------------- /aoc/2022/input/19.txt: -------------------------------------------------------------------------------- 1 | Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 3 ore and 16 obsidian. 2 | Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 4 ore and 7 obsidian. 3 | Blueprint 3: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian. 4 | Blueprint 4: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian. 5 | Blueprint 5: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 8 obsidian. 6 | Blueprint 6: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 9 obsidian. 7 | Blueprint 7: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 3 ore and 18 obsidian. 8 | Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 17 obsidian. 9 | Blueprint 9: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 2 ore and 20 obsidian. 10 | Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 4 ore and 13 obsidian. 11 | Blueprint 11: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 17 clay. Each geode robot costs 3 ore and 11 obsidian. 12 | Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 4 ore and 8 obsidian. 13 | Blueprint 13: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 4 ore and 8 obsidian. 14 | Blueprint 14: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 6 clay. Each geode robot costs 3 ore and 16 obsidian. 15 | Blueprint 15: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 12 obsidian. 16 | Blueprint 16: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 8 obsidian. 17 | Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 11 clay. Each geode robot costs 3 ore and 15 obsidian. 18 | Blueprint 18: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 12 obsidian. 19 | Blueprint 19: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 10 clay. Each geode robot costs 2 ore and 10 obsidian. 20 | Blueprint 20: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 3 ore and 12 obsidian. 21 | Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 10 clay. Each geode robot costs 2 ore and 7 obsidian. 22 | Blueprint 22: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 12 clay. Each geode robot costs 4 ore and 19 obsidian. 23 | Blueprint 23: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 2 ore and 15 obsidian. 24 | Blueprint 24: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 13 obsidian. 25 | Blueprint 25: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 3 ore and 14 obsidian. 26 | Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 9 obsidian. 27 | Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 10 clay. Each geode robot costs 2 ore and 7 obsidian. 28 | Blueprint 28: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian. 29 | Blueprint 29: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 2 ore and 13 obsidian. 30 | Blueprint 30: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 12 clay. Each geode robot costs 3 ore and 8 obsidian. 31 | -------------------------------------------------------------------------------- /aoc/2022/input/24.txt: -------------------------------------------------------------------------------- 1 | #.######################################################################################################################## 2 | #<..<^>vv^.>>>^.>v.^v<.^<>><^v>v^v><><^<<.<..^^..^>v>><>^>>>vv>v.<^v>v<^v^>.^<^^<<><<<>^vv^>.^># 3 | #<>><>^^<.^<>^^>^^><^><^>v>v>v>>>^><<<>>v<>v>^v>>^v>v<<<.>^<<<<<>>v<<>^v^>.>>v<<># 4 | #>.^>.>v<><^^>..^....v>^^>>^v><<<<<^<^v><.v<.>..<>.>^v^^^.>^^><^v^^v<<....>^>v><<>v>^>^>v^^v><# 5 | #<^>^>v>.<^<.v<<<>^>vv^<vvv<^vv^v^<>vv^<><<>v<>v.vvv.>>v^>><<<>^^v><^^v^^v^^v>>v><<.>^vv.^<# 6 | #>>^><>.>>><><.<>v><<><>vvvv>^><>vv^>^<>^<>^^>><^^>.vvv^<^><^.>vvvv>^.vv<^><^.^vvv<<# 7 | #<>^.v.<^.v<>^^^^^>><^<..v<^v<>>.>>^><^v<^^v^>v^<.<^<.><^^<>^v^><.<>..^>v^.v>.^<><>^.^v><>>>>^.<# 8 | #><^>^<^.^<^.vv>.>v^<.>.<>.v<>>v^><><<<<^vv<<.v^<>><.^<^..^^>.v^<<<>^.v^<>^<.^<<>><# 9 | #<>vvv.v.<^<>^v.v><^^.>^>^<^v.v>>v<^^^<^<^^v.^.><<<>.<<>>^>>^<>.^>v<^.v.vv^v^^^..>.v<.vv<>.>>>>.^><><# 10 | #<>v.^><<<<>>.<<^v>.>v^<>^v>^>>.v.>>^.v^^^><^<<<^^.^v^^>^vv<<>>>.><.^^<<^^<<.<<><^<^^.v><# 11 | #>>><v>^v<^^v^vv><^.v..v.v.>vv><<^...><^v>>^<><>^>>^>^^<>>>.<^^>.v^^^.><>v<>.<# 12 | #><^^^v<><<<^v>^^>^<<>>.<^^vvv<<>^v^<.<>^v^..v>v<.<^^v><^<<<^v.><>vv><^vvv>^v^.^<.>vvvvv<>><># 13 | #>^<>^v^^v<^vvvvv^v.<<>v>>>^<^^<..>^<^<^.>v<>^>^>><>v.vvv.^^v.^^>^<>>^^v<>v<<<^^.>>^>>^>.>>><><>^^^>>^>><<^^^>>v<>>>>^v<^^>.><<^>^^^<.<>v<^><><>>>v>.>.>vv>.v<.<^^>>vv^v>>vv># 15 | #>>.>.vv>^>><^>^.^v>^v<>..<>^^.>..vv<^v>>^.vvv>>^^^vv^^v>^<^.><<v^<<>><^v>>^>^^.v^<^^<>><># 16 | #<^>^>v<^.v^vv^^v>^^v>v^^vv^v^vv>^.><.v<.<><>v^<><<<<>.v^v^<<>^<<>>>>>><.^^^<><<>^v^^# 17 | #.<^^>>v<^^<^>>>>.vvv^>^^><^><.<>v^^vv^v<^>>^<.>^>><^<^><<..v># 18 | #<.>>^.v^.^.v^v<>v>v>v^vv^^<^<<>^^><<><.v<>>^>vv^^>>v<><^^<>^v<vv.vvv>v<.^v^.^><>v>>vvv># 19 | #<>^.v<^v>>>v>v<>^>v^vv<^<.^v.vv^>.v..>>.>vv>>>v^.^^>>^>>><><><>v>>..<^.>^v<^^v^<>>>.^^<^<.v>^>vvv># 20 | #<^.v^<><<..^^vv>>>^vv.>^<>v^v^v^.>^<^<.>>^v><^^v>>^<<<..v<^>v>^vv>^vv^>^v.>>^<<^^>.>>^>^>^^vv.<^v^>>>.>>><^>>v^^^.vv.<<^v^.>v>><^>v.v><^<<>v>v^vv.v<.><><>.^v>.>>>^<>.^>^>v.^v^>v^<><.<<<^<^><^^^<# 22 | #>^<>v>v>.>><>.><..vvvv<>vv<<^^v<>v><^<><<^v>^v<<.<<^^<.v>.<<<>vvv.v>>v^v.>^<>>.<<^v.^^v<^^v.^<.v<<>...<<<<^^^v^.<.>^^<>>^>v^^^^<^v^<><^<<^^.^^<^vv^v<<^^<^<.^># 24 | #<^.^^.<.<<^v^<..><.^v<<>v.<^vv><v>>v><<^.<.>^>v>>>.<><.>^v>>v^v<.^^>.v^v>^><^^v^v>>vv>^.v<>^># 25 | #.>^.v<.>>^<><^>v><.<>>^^vv^.<.>.v>>v.>^><<..v<>v>v>>v><>v^^<^>^<<>^.<<^>v.>v^>vv<>># 26 | #<><.^^^^<>>.<^v.>^<<>v>.>>vv^^<>v^v<^.<.v^v>>>>^><^vvv.>>>v<<<.^^.v.^v.><<.v<>>>^.^v>^vvv.<>v^<^v^<^v<^<><^^^v^<# 27 | ########################################################################################################################.# 28 | -------------------------------------------------------------------------------- /aoc/2022/input/25.txt: -------------------------------------------------------------------------------- 1 | 1=0=01=0=2111-1211 2 | 1==21= 3 | 20-- 4 | 1-=1200=-=0 5 | 211==12=2=0111== 6 | 2=-10 7 | 1221=221=0-1=- 8 | 12=02=-12020=12=01- 9 | 12112101 10 | 20 11 | 120120=21=1002-1 12 | 10==1-02=1 13 | 1=11200001-=-- 14 | 1=222-1=012=2 15 | 20===1-1102-= 16 | 1020 17 | 102=-==-=2- 18 | 112-2112-00012- 19 | 1010=--121 20 | 202022=-=2-22= 21 | 122==1=1020011=-00 22 | 10212==-0 23 | 2=--12020=1-0=-2=- 24 | 1110-1-2 25 | 20==210221=-21--12 26 | 1=-02--=22=-122 27 | 2=-=0=00=1--1-2=-- 28 | 2==2==2- 29 | 2=12=1 30 | 2=01= 31 | 202=20202-000 32 | 1=0-=020021022012 33 | 2=0-011-=2=-0-=21 34 | 1=211 35 | 1-=1=11=--010=--- 36 | 1000020-12== 37 | 2-=122-1211-0= 38 | 10=2220122012 39 | 2=21-01=212 40 | 10111==2=2-12 41 | 111 42 | 1=2---2211=2011=-- 43 | 1--=0000=1-020 44 | 2=02-=- 45 | 1-011= 46 | 12020-0=-1-220100 47 | 2-==000=21=1 48 | 2-0100000-12-2-= 49 | 1-=1 50 | 1221=2-1==02-=202 51 | 200 52 | 122-2-0 53 | 10=2101-22 54 | 1==-120-1 55 | 2=2=2=-11--==-== 56 | 2111-=2=-=-2 57 | 1-- 58 | 1-0=10-0112-12= 59 | 10= 60 | 2=01=1=-=20= 61 | 1= 62 | 1211-2=-1= 63 | 222= 64 | 122=2-1-0 65 | 1-2=20-=02122-1 66 | 1==-=2===0-=1100--11 67 | 12-0=201=10=-= 68 | 1=01=2=22-2-1-1 69 | 120==222100=0 70 | 11=-=--12=2-1101 71 | 102=1221=---0==021 72 | 2-=-2=202-=-== 73 | 100=1=02020-221= 74 | 1=0=-220= 75 | 1001- 76 | 20==2==1-1 77 | 1=2-2=2=-12= 78 | 10=0--2 79 | 10-202-2002=22= 80 | 2=2= 81 | 1-011=0=-12--- 82 | 1002220 83 | 2= 84 | 1--=2---111 85 | 222==2 86 | 11100 87 | 1=0=201 88 | 1--02- 89 | 1=11-==0=021 90 | 1-=00= 91 | 1==12-20-=002001= 92 | 1=0=-=21- 93 | 1000-1=0-0=1=01-2- 94 | 2== 95 | 1-0 96 | 1=101-0-1 97 | 1=0= 98 | 11=2==-0-2202-0= 99 | 10-0=0=1-002 100 | 1-=0210=01120- 101 | 1112=2-0-2=-01 102 | 1-1=022=21 103 | 2=1-2--120 104 | 10002--0=220-0-2=12 105 | 11002102100 106 | 11000-2-12 107 | 120=-==1-2-= 108 | 21 109 | 11 110 | 2=121- 111 | 1== 112 | 1=- 113 | 1-=--2=- 114 | 2=-10-=0 115 | 2200-1- 116 | 2=21-1200== 117 | 1-102210=002=--112 118 | 1-10 119 | 122=202=201-=-10-1 120 | 2212121=02102 121 | 21=2-211=-1-20- 122 | 101-=01-1 123 | 200012112= 124 | 22=21201=22 125 | 1-1212=1-=1 126 | 1212-==1=01 127 | 22==--= 128 | 1=-2-1-==020-10-= 129 | 1=1210=--00 130 | 1=--=1= 131 | 2010111-00111-2=2 132 | 11=21-0=2-01 133 | 21= 134 | 1=-0-220 135 | 102-=0 136 | 1=---0- 137 | 1-1122-=121222--0 138 | 10110=1-20--1-1 139 | 20=--21220-= 140 | 1=---22- 141 | 2-000===1101= 142 | 20- 143 | 10== 144 | -------------------------------------------------------------------------------- /aoc/2022/q/01.q: -------------------------------------------------------------------------------- 1 | / https://adventofcode.com/2022/day/1 2 | 3 | /ingestion 4 | inp: read0`:input/01.txt 5 | loads: sum each{(0,where null x)_ x}"I"$inp 6 | 7 | loads: value {"(sum ",x,")"} ssr[;" ";";sum "]" "sv inp /Sean Ang 8 | loads: value each"++"vs"+"sv inp /Cillian Murphy 9 | loads: desc deltas asc s*(~':)s:sums"J"$inp /Cillian straight-vector 10 | loads: (sum get::) each "\n\n"vs"c"$read1 `:test/01.txt /Nick Psaris 11 | 12 | / part 1 & part 2 13 | (first;sum 3#::)@\:desc loads 14 | 15 | 16 | // Péter Györök 17 | d1:{sum each"J"$"\n"vs/:"\n\n"vs"\n"sv x}; 18 | //d1:{sum each{(0,where null x)cut x}"J"$x}; 19 | max d1 inp 20 | sum 3#desc d1 inp 21 | 22 | // András Dőtsch 23 | i:sum@'get@'",,"vs","sv read0`:01.txt 24 | max i //1 25 | sum 3#desc i //2 26 | 27 | // Tadhg Downey 28 | f: {max sum each (0,where 0N=l)_l:"J"$read0 x} 29 | g: {sum 3#desc sum each (0,where 0N=l)_l:"J"$read0 x} 30 | 31 | // Zsolt Venczel 32 | data: "J"$inp 33 | indexes: where 0N ~/: data 34 | deer: (enlist first[indexes] # data), 1 _/: indexes _ data 35 | maxCal: max sum each deer 36 | top3: sum 3 # desc sum each deer 37 | 38 | // Roman Pszonka 39 | t:"I"$inp 40 | sorted:desc sum each _[0,1+where t=0N;t] / split, sum each section, and sort 41 | sorted[0] / first element 42 | sum sorted[til 3] / sum of first 3 elements 43 | 44 | // Attila Vrabecz 45 | x:"J"$inp 46 | max(0|+)scan x 47 | sum 3#desc{x*0=next x}(0|+)scan x 48 | 49 | // Mark Street 50 | max sum each (where null i) cut i:0N,"J"$inp 51 | 52 | // Muneish Adya 53 | //part 1 54 | (l:"J"$inp);max l:(+/')(0,(&)0N=l)_l 55 | //part 2 56 | sum 3#desc l 57 | 58 | // Cillian Reilly 59 | (max;sum 3#desc@)@\:deltas asc s*(~':)s:sums"J"$inp 60 | 61 | // Sean Ang 62 | max value {"(sum",x,")"} ssr[;" ";";sum "] " " sv inp 63 | 64 | // David Crossey 65 | (first;sum 3#desc@)@\:sum each where[null 0N,r] _ r:"J"$read0 inp -------------------------------------------------------------------------------- /aoc/2022/q/02.q: -------------------------------------------------------------------------------- 1 | / https://adventofcode.com/2022/day/2 2 | 3 | / ingestion 4 | inp:read0 `:input/02.txt 5 | 6 | // András Dőtsch & Nick Psaris 7 | i:flip ("CC";" ") 0: `:test/02.txt 8 | k:"ABC" cross "XYZ" 9 | / part 1 10 | s:k!raze 1 2 3+/:2 rotate[-1]\ 3 6 0 11 | sum s inp 12 | / part 2 13 | s:k!raze 0 3 6+/:2 rotate[1]\ 3 1 2 14 | sum s inp 15 | 16 | // András Dőtsch 17 | /A shorter vesion with less insights. 18 | i:read0`02.txt 19 | s1:asc[distinct i]!3 6 0 0 3 6 6 0 3+9#1 2 3 20 | sum s1 inp 21 | s2:asc[distinct i]!3 1 2 1 2 3 2 3 1+9#0 3 6 22 | sum s2 inp 23 | 24 | 25 | // Attila Vrabecz 26 | i:-88h+7h$("cc";" ")0:inp 27 | sum 1+i[1]+3*mod[;3]2-(-/)i 28 | sum(3 1 2 mod[;3]sum 3 2+i)+3*i 1 29 | 30 | // Zsolt Venczel 31 | r1: `A`B`C!(`X`Y`Z!(4; 8; 3); `X`Y`Z!(1; 5; 9); `X`Y`Z!(7; 2; 6)) 32 | r2: `A`B`C!(`X`Y`Z!(3; 4; 8); `X`Y`Z!(1; 5; 9); `X`Y`Z!(2; 6; 7)) 33 | fn: {sum {x[first -1_y][first 1_y]}[x] each {`$" " vs x} each inp} 34 | fn each (r1; r2) 35 | 36 | // Tadgh Downey 37 | /Calculated all the outcomes by hand :joy: 38 | p1Score:`A`B`C`X`Y`Z!(1 2 3 1 2 3) 39 | p1Outcome:(rps cross rps:1+til 3)!3 6 0 0 3 6 6 0 3 40 | p2Score:`A`B`C`X`Y`Z!(1 2 3 0 3 6) 41 | p2Outcome:(1 2 3 cross 0 3 6)!(3 1 2 1 2 3 2 3 1) 42 | d2:{[f;s;o] sum scores[1]+o flip scores:s("SS";" ")0:inp} 43 | 44 | // George Berkeley 45 | s:(" " vs) each inp 46 | m:{neg["i"$x]+"i"$y} 47 | p1:(4 8 3;1 5 9;7 2 6). 48 | p2:(3 4 8;1 5 9;2 6 7). 49 | sum {p1 ("A";"X")m'x} each s / part 1 50 | sum {p2 ("A";"X")m'x} each s / part 2 51 | 52 | // Cillian Reilly 53 | i:7h$("CC";" ")0: inp 54 | 2 sum/(3*mod[;3]2+neg(-).;-87+last@)@\:i 55 | 2 sum/({x+3*not x}mod[;3]sum 2 1+;3*-88+last@)@\:i 56 | 57 | // Attila Vrabecz 58 | i:-88h+7h$("cc";" ")0:`02.txt 59 | sum 1+i[1]+3*mod[;3]2-(-/)i 60 | sum(3 1 2 mod[;3]sum 3 2+i)+3*i 1 61 | 62 | // Stephen Taylor 63 | strategy: inp[;0 2] 64 | rounds: string`BX`CY`AZ`AX`BY`CZ`CX`AY`BZ 65 | score: sum 1+ rounds? :: 66 | play:rounds!rounds[;0],'"XZYZYXYXZ" 67 | score each 1 play\strategy /parts 1 & 2 68 | 69 | // Sujoy Rakshit 70 | d:("B Y";"A X";"C Z";"A Z";"C Y";"B X")!(3;3;3;0;0;0) 71 | d1:"XYZ"!(1;2;3) 72 | d2:("A Y";"B Y";"C Y";"A X";"B X";"C X";"A Z";"B Z";"C Z")!("A X";"B Y";"C Z";"A Z";"B X";"C Y";"A Y";"B Z";"C X") 73 | 74 | f:{sum (z x[;2]),6^y x} 75 | 76 | // Part 1 77 | f[inp;d;d1] 78 | // Part 2 79 | f[d2 inp;d;d1] -------------------------------------------------------------------------------- /aoc/2022/q/03.q: -------------------------------------------------------------------------------- 1 | / https://adventofcode.com/2022/day/3 2 | 3 | inp: read0`:input/03.txt 4 | 5 | // András Dőtsch 6 | f:sum {1 + .Q.an?first inter/[x]} each 7 | f 2 0N#/: inp 8 | f 0N 3# inp 9 | 10 | // Péter Györök 11 | d3out:{sum 1+.Q.an?raze distinct each x}; 12 | {p:((count each x)div 2)cut'x; d3out p[;0]inter'p[;1]} inp 13 | d3out(inter/)each 3 cut inp 14 | 15 | // Cillian Reilly 16 | sum each 1+.Q.an?('[first;inter/])each'(2 0N#/:;0N 3#)@\:inp 17 | 18 | // George Berkeley 19 | ps:.Q.a,.Q.A 20 | sum {1+where ps=first (first t) inter last t:(0,div[;2] count x) _ x} each inp / part 1 21 | sum {1+where ps=first (inter/)x} each (3*til div[;3] count inp) _ inp / part 2 22 | 23 | //Tadhg Downey 24 | pr:a!1+til count a:.Q.a,.Q.A 25 | f:{sum raze {distinct (inter). x(0,floor c%2)_til c:count x}each pr read0 x} 26 | g:{sum {distinct (inter/) x}each (3*til "j"$count[l]%3)_l:pr read0 x} 27 | 28 | // Stephen Taylor 29 | / part 1 30 | err: {first x where x in y} . {(2,count[x]div 2)#x} :: / identify error 31 | priorities: " ",.Q.a,.Q.A 32 | 33 | sum priorities?err each inp 34 | 35 | / part 2 36 | groups: {_[;x]where count[x]#1 0 0} inp / group in threes 37 | badge: first distinct ({x where x in y}/) :: / identify badge 38 | sum priorities?badge each groups 39 | 40 | // Sujoy Rakshit 41 | d:(.Q.a!1+til 26),.Q.A!27+til 26 42 | f:{#[(0N;div[count x;2])] x} 43 | /Part 1 44 | sum ('[;]/[(d;first;(inter/);f)] each inp) 45 | /Part 2 46 | sum ('[;]/[(d;first;inter/)] each 0N 3#inp) 47 | 48 | // Ajay Rathore 49 | f:{sum 1+('[distinct;inter/]').Q.an?x} 50 | f 2 0N#/: inp 51 | f 3 cut inp 52 | 53 | // David Crossey 54 | score:(string .Q.a,.Q.A)!(1+til 52) 55 | (sum score distinct each (inter/)@/:) each (ceiling[count'[inp]%2] cut' inp;3 cut inp) -------------------------------------------------------------------------------- /aoc/2022/q/04.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/4 2 | 3 | inp: read0`:input/04.txt /assignments 4 | test: read0`:test/04.txt /assignments 5 | 6 | // András Dőtsch 7 | i:("jj";"-")0:/:("**";",")0: inp 8 | sum {0>=.[*]x-y} . i 9 | sum {0>=.[*]x-reverse y} . i 10 | 11 | // Péter Györök 12 | d4:{asc each "J"$"-"vs/:/:","vs/:x} 13 | {a:d4 x;sum(a[;1;1]<=a[;0;1]) or a[;0;0]=a[;1;0]} inp 14 | {a:d4 x;sum a[;1;0]<=a[;0;1]} inp 15 | 16 | // Cillian Reilly 17 | sum{any(all;any)@\:/:(within)./:(reverse\)x}each "J"$"-"vs/:/:","vs/: inp 18 | 19 | // Tadhg Downey 20 | {sum{all[(in/)reverse x]|all (in/)x:("J"$"-"vs'x)[;0]+til each 1+abs value each x}each csv vs'x} inp 21 | {sum{any (in/)x:("J"$"-"vs'x)[;0]+til each 1+abs value each x}each csv vs'x} inp 22 | 23 | // Sujoy Rakshit 24 | l:{(::;rotate[1;])@\: flip ("II";"-")0: "," vs x} each inp 25 | sum {any (all')(within') . x} each l 26 | sum {any (any')(within') . x} each l 27 | 28 | // Stephen Taylor 29 | /part 1 30 | ass:desc each "J"$''"-"vs''","vs'inp 31 | sum ({$[any b:x=y;1b;x[1]count distinct y z+til x}[x;y;](1+)/0} / alternative 23 | /part 1 & 2 24 | 4 14 f\:inp / \ts:100 => 289 721072 25 | 4 14 g\:inp / \ts:100 => 470 1296 26 | 27 | 28 | // Nathan Swann 29 | // Next until count of distinct first 4 characters is 4 30 | // Original string count - Next string count + 4 31 | h:{c:count x; cn:count trim (next/) [{y<>count distinct y$x}[;y];x]; y+c-cn} 32 | inp h/:4 14 / Parts 1 & 2 33 | 34 | // Sean Ang 35 | mtake:{neg[y]sublist x,z}\[();;] 36 | fn:{1+first where x=count each distinct each mtake[x;y]} 37 | 4 14 fn\:inp 38 | 39 | // Tom Ferguson & Nick Psaris 40 | u:{[n;x;i] not n=count distinct x i} 41 | f:{[n;x]n+first u[n;x] (1+)/ til n} 42 | 4 14 f\:inp 43 | 44 | / 45 | as Ajay also pointed out the space is pretty small 46 | so as a side-challenge it's interesting to see if we can get some more speed out 47 | and it's not obvious 48 | 49 | q)\ts:100 f[14]x 50 | 289 1376 51 | 52 | q)a:{[n;x] n+?[;b]{x?x}each flip x til[count x]+/:b:til n} 53 | q)\ts:100 a[14]x 54 | 166 1032912 55 | 56 | and most of that is coming from {x?x} 57 | 58 | q)U:{[n;x;i] not n~a?a:x i} 59 | q)F:{[n;x]n+first U[b;x] (1+)/ b:til n} 60 | q)\ts:100 F[14]x 61 | 220 1008 62 | \ 63 | 64 | // David Crossey 65 | raze {x+flip[count each' distinct each' x#''{1_'x}\[inp]]?'x} each 4 14 -------------------------------------------------------------------------------- /aoc/2022/q/08.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/8 2 | 3 | inp: read0`:test/08.txt /trees 4 | 5 | // Stephen Taylor & Cillian Reilly 6 | rot: flip reverse:: /rotate 90° clockwise 7 | tor: reverse flip:: /rotate 90° anticlockwise 8 | c4: {til[4]{y tor/x z}[x]'3 rot\y} /apply x to y from 4 directions 9 | vn: not(=':)maxs:: /visibility from N 10 | 2 sum/max c4[vn] inp /part 1 11 | vdw: {reverse[til count first x]&/: 12 | 1+((sum mins 1_)'')x>-1_'(1_)\'[x]} /viewing distance from W 13 | 2 max/prd c4[vdw] inp /part 2 14 | 15 | \ 16 | // Péter Györök 17 | {a:"J"$/:/:x; 18 | op:{x>maxs each -1_/:-1,/:x}; 19 | sum sum max(op a; flip op flip a; reverse flip op flip reverse a; 20 | reverse each op reverse each a)} inp 21 | {a:"J"$/:/:x; 22 | op:{[m;x]0,/:{[m;x;y]$[y maxs y; $[s < count y; s+1; s]} 42 | max max {{[y;x] (*/) ( 43 | ds[hdata[y][x]] reverse x # hdata[y]; 44 | ds[hdata[y][x]] (x+1) _ hdata[y]; 45 | ds[vdata[x][y]] reverse y # vdata[x]; 46 | ds[vdata[x][y]] (y+1) _ vdata[x] 47 | )}[x] each rng} each rng 48 | 49 | // Tadhg Downey 50 | {(sum/)(|/)(flip reverse(>':)maxs reverse fi;reverse(>':)maxs reverse x;flip(>':)maxs fi:flip x;(>':)maxs x)} inp 51 | rvd: {v'[t;reverse t:til count x;nxtGr[x]]} / Row view distance 52 | nxtGr: {[l] {[l;i] first w where (w:where[l>=l i])>i}[l]each til count l} / Next greater index 53 | {(max/)prd(flip reverse each rvd each reverse each fi;reverse each rvd each reverse each x;flip rvd each fi:flip x;rvd each x)} inp 54 | 55 | // Cillian Reilly 56 | // Cillian Reilly 57 | trees: 3(flip reverse@)\inp 58 | map: ((reverse flip@)/)'[til 4;] 59 | 60 | p1: not(=':)maxs@ 61 | p2: {reverse[x]&/:1+(sum mins 1_)each'y>x _\:/:y} 62 | 63 | 2 sum/max map p1 each trees 64 | 2 max/prd map p2[til count first trees;]each trees 65 | 66 | 67 | / Sean Ang 68 | trees: i 69 | search:{[trees] 70 | ( 71 | fn trees; 72 | reverse each fn reverse each trees; 73 | flip fn flip trees; 74 | flip reverse each fn reverse each flip trees 75 | ) } 76 | 77 | /p1 78 | fn:{differ each maxs each x} 79 | sum raze (|/) search[trees] 80 | 81 | /p2 82 | c:{(-1+count x)^first 1+where (1_x)>=first x} 83 | fn:{flip{c each z _' x}[x]\[();til count x]} 84 | max raze (*/) search[trees] 85 | 86 | -------------------------------------------------------------------------------- /aoc/2022/q/09.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/9 2 | 3 | inp: read0`:test/09.txt 4 | 5 | // Cillian Reilly and Nick Psaris 6 | s:sums("RLDU"!(1 0;-1 0;0 -1;0 1))where (!/) ("CJ";" ")0:inp 7 | move:{$[1=d[`:]-40000000 27 | / ^-- ungroup and exec idea from Péter Györök 28 | 29 | // Péter Györök 30 | d9:{[t;x]a:" "vs/:x; 31 | dir:raze a[;0]; 32 | amt:"J"$a[;1]; 33 | dir2:dir where amt; //raze amt#'dir; 34 | mH:("UDLR"!(0 -1;0 1;-1 0;1 0))dir2; 35 | pH:enlist[0 0],sums mH; 36 | step1:{d:y-x;if[1 r/c; increment 77 | move: {[d;s;m]s,1_("J"$m 2)move1[d m 0;]\last s}[MD;;] 78 | move1: {follow @[y;;+;]. x} /move 1 space 79 | follow: {x+0 0,signum{x*any 1max abs d:y - x;x+signum d;x]}\ 93 | /part 1 94 | tail: f head 95 | count group tail 96 | /part 2 97 | / each knot tail becomes head of next knot 98 | lastknot:9 f/ head 99 | count group lastknot 100 | 101 | // Ahmed Shabaz 102 | t:flip`m`n!raze@'($[`;];$["J";])@'flip" "vs'inp 103 | d:`L`R`U`D!(-1 0; 1 0; 0 1; 0 -1) 104 | t:update sums H from ungroup update H:{y#enlist d[x]}'[m;n] from t 105 | f:{$[any 1abs(-1_1,i)-240#til 40 10 | 11 | // Péter Györök 12 | /no iterators! 13 | .d10.ocr:()!(); 14 | .d10.ocr[529680320]:"A" 15 | .d10.ocr[1067881856]:"B" 16 | .d10.ocr[512103552]:"C" 17 | .d10.ocr[1067616256]:"F" 18 | .d10.ocr[1059153984]:"K" 19 | .d10.ocr[1057230912]:"L" 20 | .d10.ocr[33955712]:"J" 21 | .d10.ocr[1066550784]:"P" 22 | d10:{[part;x]a:" "vs/:x; 23 | t:1+a[;0]like"addx"; 24 | d:1,1+sums "J"$a[;1]; 25 | val:d where t; 26 | if[part=1; 27 | ind:20+40*til 6; 28 | :sum ind*val ind-1]; 29 | r:40 cut (val-til[240]mod 40)within -1 1; 30 | //-1 " #"r; 31 | R2::r2:2 sv/:raze each 5 cut flip R::r; 32 | .d10.ocr r2} 33 | d10p1:{d10[1;x]} inp 34 | d10p2:{d10[2;x]} inp 35 | 36 | / 37 | // Stephen Taylor 38 | /part 1 39 | X: {1+\raze{((0,;0^)@null x)@'x}"J"$5_'x} inp /register X at each cyle 40 | sum{x*y x-2}[20 60 100 140 180 220] X 41 | /part 2 42 | show 40 cut".#"{(til[count x]mod 40)within'-1 1+/:0^prev x} X 43 | 44 | // Cillian Reilly 45 | r:1+sums raze distinct each 0N,/:first(" J";" ")0: inp 46 | {sum y*x -2+y}[r;20 60 100 140 180 220] 47 | {40 cut(".#")1b,(mod[;40]1+til count x)within'-1 1+/:x} -1_r 48 | 49 | // George Berkeley 50 | s:{" " vs x}@' inp 51 | xs:1+sums{("J"$x 1;0)("addx";"noop")?x 0}@'s 52 | c:sums{(2 1)("addx";"noop")?x 0}@'s 53 | sum t*xs neg[1]+c binr t:20 60 100 140 180 220 / part 1 54 | fc:1^xs neg[1]+c binr 1+til max c 55 | 40 cut (".#"){mod[x;40]within(-1;1)+fc x}@'til 240 / part 2 56 | 57 | // András Dőtsch 58 | f:{$[x~"noop";0;0,"J"$last" "vs x]} 59 | sum(sums 1,raze f each inp)[c-1]*c:20+40*til 6 60 | ".#"2>abs(6 40#til 40)-40 cut -1_(sums 1,raze f each inp) 61 | /alternative 62 | noop:0;addx:0, 63 | i:1+\get","sv inp 64 | sum i[c-2]*c:20+40*til 6 65 | ".#"40 cut 2>abs(-1_1,i)-240#til 40 66 | 67 | // Zsolt Venczel 68 | d10data: {{(x[0];"J"$x[1])}[" " vs x]} each inp 69 | 70 | r: (enlist 1), raze {v:: 1; {$["addx" ~ x[0]; {r: (v; v + x); v:: v + x; r}[x[1]]; v]} each x}[d10data] 71 | ans1: sum {r[x-1]*x}[(20 60 100 140 180 220)] 72 | ans2: {40 cut (((-1 _ r) - 1) <= x) & (x <= (-1 _ r) + 1)}[raze {til 40} each til 6] -------------------------------------------------------------------------------- /aoc/2022/q/13.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/13 2 | 3 | inp: read0`:input/13.txt 4 | 5 | I: 2 cut .j.k each inp where count[inp]#110b 6 | 7 | b: {x@/:(y;z)} / 'both' combinator 8 | 9 | cmp:{ 10 | $[all b[type;x;y]<0; `long$x-y; 11 | any b[count;x;y]=0; .[-] b[count;x;y]; 12 | r:cmp . b[first;x;y]; r; 13 | cmp . b[1_(),;x;y] ] } 14 | 15 | sum 1+where 1>cmp .' I /part 1 16 | 17 | qs: {$[2>count x; x; 18 | raze(.z.s;::;.z.s)@'x(group signum x cmp\:first x)@-1 0 1 19 | ]} 20 | 21 | `A`B set'b[.j.k;"[[2]]";"[[6]]"]; 22 | J: qs(A;B),raze I 23 | prd 1+b[where ~/:[;J]::; A; B] /part 2 24 | 25 | 26 | \ 27 | // András Dőtsch 28 | I:2#'3 cut p@'inp 29 | cmp:{ 30 | $[(0>type x)&0>type y; `long$x-y; 31 | (0=count x)|0=count y; count[x]-count y; 32 | r:cmp[first x;first y]; r; 33 | cmp[1_(),x;1_(),y]] 34 | } 35 | sum 1+where 1>cmp .' I //1 36 | qs:{$[2>count x;x;qs[x where 0>r],(x where 0=r),qs[x where 0tr:first (tmp except 0),0;tr; 50 | signum count[x]-count[y]] 51 | ]]}; 52 | if[part=1; :sum 1+where -1=.[cmp]'[a]]; 53 | b:raze[a],dl:(enlist enlist 2f;enlist enlist 6f); 54 | sort:{[cmp;b] 55 | if[1>=count b; :b]; 56 | cr:cmp[first b]'[1_b]; 57 | left:b 1+where 1=cr; 58 | right:b 1+where -1=cr; 59 | .z.s[cmp;left],(1#b),.z.s[cmp;right]}; 60 | b2:sort[cmp;b]; 61 | prd 1+where any b2~\:/:dl} 62 | d13[1] inp 63 | d13[2] inp 64 | 65 | // Sean Ang 66 | prse:{get ssr[;"[[]";"enlist("] ssr[;"]";")"] ssr[;",";";"] x} 67 | pairs:2 cut packets:prse each {x where not x~\:""} inp 68 | cmp:{ 69 | while[any count each (x;y); 70 | if[0=count x;:1b]; 71 | if[0=count y;:0b]; 72 | a:first x; b:first y; 73 | $[any 0<=(type a;type b); 74 | [ 75 | if[0>type a;a:enlist a]; 76 | if[0>type b;b:enlist b]; 77 | res:.z.s[a;b]; 78 | if[not (::)~res;:res] 79 | ]; 80 | [ 81 | if[ab;:0b]; 83 | ] 84 | ]; 85 | x:1_x; y:1_y 86 | ]; 87 | } 88 | / p1 89 | sum 1+where cmp ./: pairs 90 | / p2 91 | prd {1+where in[;0 1] iasc sum each 1b~''x cmp\:/:x}(enlist enlist 2;enlist enlist 6),packets 92 | 93 | -------------------------------------------------------------------------------- /aoc/2022/q/14.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/14 2 | 3 | inp: read0`:test/14.txt 4 | 5 | range: {$[.[=]x;first x;{x+til y-x-1}. asc x]} / x => y inclusive 6 | between: .[,'] (range') flip :: 7 | line: {[map;pts] ./[map;between pts;:;] 1} / draw rock line 8 | 9 | Map: { /air and rock 10 | I: (reverse'')raze{1_(;)prior x}@'(get'') " -> "vs/:x; 11 | ((2 0+0 1000|max raze I)#0)line/I } inp 12 | 13 | fall: {[map;xy] first p where not map ./:p: xy+/:(1 0;1 -1;1 1;0 0) } 14 | drop: {[map] .[map;p;:;] 2*count[map]>1+first p: fall[map]/[0 500] } 15 | 16 | sum raze 2=drop/[Map] /part 1 17 | 18 | drop2: {[map] .[map;;:;2] fall[map]/[0 500] } 19 | sum raze 2={not x . 0 500} drop2/Map /part 2 20 | 21 | 22 | disp: {[map;xy] /display map with sand at xy 23 | m: .[map;;:;3] xy; / mark sand 24 | r: (first;last)@\:where any m; / range of rock and sand 25 | lbl: (;xy 0;) . r; / col labels 26 | c: range r+ -1 1; / display columns 27 | s: string[til count m],'" "; / side labels 28 | s: {(m+1)$neg[m:max count each x]$x}s; / aligned 29 | w: count s 0; / side width 30 | h: (w+count c;3)#" "; / header 31 | h: flip@/[h;w+c?lbl;:;] string lbl; / with labels 32 | h, s,' ".#o+"m[;c] }[;0 500] 33 | 34 | \ 35 | 36 | //// k4 Topicbox 37 | 38 | //// #adventofcode 39 | 40 | // Péter Györök 41 | 1 2 {[part;x] 42 | a:"J"$","vs/:/:" -> "vs/:x; 43 | f:{if[0=count y;:()];c:asc(x;y);x:c 0;y:c 1;$[x[0]=y[0]; 44 | x[0],/:x[1]+til 1+y[1]-x[1];(x[0]+til 1+y[0]-x[0]),\:x[1]]}; 45 | c:reverse each distinct raze raze f':'[a]; 46 | start:min enlist[0 500],c; 47 | size:1+max[c]-min[c]; 48 | maxh:max[c[;1]]; 49 | if[part=2; start[1]:min(start 1;500-maxh)]; 50 | b:c-\:start; 51 | origin:0 500-start; 52 | end:max b; 53 | if[part=2; end[0]+:1;end[1]:max(end 1;origin[1]+maxh)]; 54 | map:.[;;:;"#"]/[(1+end)#" ";b]; 55 | if[part=2; map,:enlist (1+end[1])#"#"]; 56 | drop:{[pos;x] 57 | i:x 0; 58 | map:x 1; 59 | moved:1b; 60 | finish:0b; 61 | while[moved; 62 | moved:0b; 63 | nudge:$[" "=map[pos[0]+1;pos[1]];0; 64 | " "=map[pos[0]+1;pos[1]-1];-1; 65 | " "=map[pos[0]+1;pos[1]+1];1; 66 | 0N]; 67 | if[not[" "=map . pos] or (pos[0]>=count map) or 68 | (pos[1]<0) or (pos[1]>=count first map); 69 | nudge:0N; finish:1b]; 70 | if[not null nudge; 71 | moved:1b; 72 | pos+:(1;nudge); 73 | pos[0]:count[map]^pos[0]+first where 74 | not" "=(1+pos[0])_map[;pos[1]]; 75 | ]; 76 | ]; 77 | if[not finish;i+:1;map:.[map;pos;:;"o"]]; 78 | (i;map)}; 79 | first drop[origin]/[(0;map)]}\: inp 80 | 81 | // András Dőtsch 82 | I:raze{1_(;)':[x]}@'(get'') " -> "vs/:inp 83 | fl:last max raze I 84 | M:(fl+3;1000)#"." 85 | {.[`M;reverse min[x]+til@'1+max[x]-min x;:;"#"]} each I; 86 | f:{[stopy] 87 | while[1b; 88 | cx:500;cy:0;stop:0b; 89 | while[not stop; 90 | $["."=M[cy+1;cx] ; cy+:1; 91 | "."=M[cy+1;cx-1];[cy+:1;cx-:1]; 92 | "."=M[cy+1;cx+1];[cy+:1;cx+:1]; 93 | stop:1b 94 | ]; 95 | if[cy=stopy;:()] 96 | ]; 97 | M[cy;cx]:"o"; 98 | ] 99 | } 100 | f[fl];2 sum/"o"=M // 1 101 | M[fl+2]:1000#"#" 102 | f[0];1+2 sum/"o"=M // 2 103 | 104 | //// Vector Dojo 105 | 106 | // Cillian Reilly 107 | npt:"J"$","vs'/:" -> "vs/: inp 108 | rocks:reverse each'raze{flip -1_/:1 next\x}each npt 109 | offset:0 499&min raze rocks 110 | start:0 500-offset 111 | rocks:rocks-\:\:offset 112 | map:#[;0b]1+(-/)(max;min)@\:raze[rocks],enlist start 113 | smear:{x|sums[x]mod 2} 114 | horizontal:{(0=dur; 30 | nq:update tflow:tflow+(dur-time)*pf npos from nq; 31 | maxflows|:exec on!tflow from nq; 32 | ]; 33 | queue:nq; 34 | ]; 35 | if[part=1; :max maxflows]; 36 | kf:1_/:key maxflows; 37 | vf:value maxflows; 38 | max max (0=sum each/:kf and/:\:kf)*vf+/:\:vf} 39 | 40 | d16[1;30] inp / part 1 41 | d16[2;26] inp / part 2 42 | 43 | 44 | 45 | // András Dőtsch 46 | //part 1 47 | i:read0`16.txt 48 | I:1!`fr`rt`to!/:{x:" "vs x;"SJS"$(x 1;(.Q.n!.Q.n)x[4];","vs raze 9_x)} each i 49 | R:desc exec fr!rt from I where 0=cubesmin[i]-1)&d<=cubesmax[i]+1}'(0 1 2)}. 56 | visited: enlist -1+cubesmin 57 | q0: enlist cubesmin 58 | surfacecnt: 0 59 | 60 | run: {[q] 61 | p:first q; 62 | $[in[;cubes] p; 63 | {surfacecnt+:1; 1_ y}[p;q]; 64 | in[p;visited]; 65 | 1_ q; 66 | {visited,:enlist x; (1_ y),cbs where {inbox x} each cbs:{x+/:dirs} x}[p;q]] } 67 | 68 | (0*maxg) 17 | *maxg = s[geo]; 18 | return s[geo]; 19 | } 20 | else if(n==N-1) 21 | { 22 | if(*maxg>=s[geo]+r[geo]) 23 | return *maxg; 24 | } 25 | else 26 | { 27 | int e = s[geo] + (N-n)*r[geo] + 28 | (((s[ore]>=B[geo][ore])&&(s[obs]>=B[geo][obs])) ? ((N-n)*(N-n-1)/2) : ((N-n-1)*(N-n-2)/2)); 29 | if(*maxg>=e) 30 | return *maxg; 31 | } 32 | int m = 0; 33 | if((s[ore]>=B[geo][ore])&&(s[obs]>=B[geo][obs])) 34 | { 35 | int s0[4] = {s[0]+r[0]-B[geo][ore],s[1]+r[1],s[2]+r[2]-B[geo][obs],s[3]+r[3]}; 36 | int r0[4] = {r[0],r[1],r[2],r[3]+1}; 37 | int m0 = f(B,maxg,n+1,s0,r0); 38 | if(m0>m)m=m0; 39 | } 40 | if((s[ore]>=B[obs][ore])&&(s[cla]>=B[obs][cla])) 41 | { 42 | int s0[4] = {s[0]+r[0]-B[obs][ore],s[1]+r[1]-B[obs][cla],s[2]+r[2],s[3]+r[3]}; 43 | int r0[4] = {r[0],r[1],r[2]+1,r[3]}; 44 | int m0 = f(B,maxg,n+1,s0,r0); 45 | if(m0>m)m=m0; 46 | } 47 | if(s[ore]>=B[cla][ore]) 48 | { 49 | int s0[4] = {s[0]+r[0]-B[cla][ore],s[1]+r[1],s[2]+r[2],s[3]+r[3]}; 50 | int r0[4] = {r[0],r[1]+1,r[2],r[3]}; 51 | int m0 = f(B,maxg,n+1,s0,r0); 52 | if(m0>m)m=m0; 53 | } 54 | if(s[ore]>=B[ore][ore]) 55 | { 56 | int s0[4] = {s[0]+r[0]-B[ore][ore],s[1]+r[1],s[2]+r[2],s[3]+r[3]}; 57 | int r0[4] = {r[0]+1,r[1],r[2],r[3]}; 58 | int m0 = f(B,maxg,n+1,s0,r0); 59 | if(m0>m)m=m0; 60 | } 61 | { 62 | int s0[4] = {s[0]+r[0],s[1]+r[1],s[2]+r[2],s[3]+r[3]}; 63 | int m0 = f(B,maxg,n+1,s0,r); 64 | if(m0>m)m=m0; 65 | } 66 | return m; 67 | } 68 | 69 | int geti(K B,S x,S y) 70 | { 71 | K i = k(0,"{x[y;z]}",r1(B),ks(x),ks(y),0); 72 | int r = i->i; 73 | r0(i); 74 | R r; 75 | } 76 | 77 | K ff(K N_, K B_) 78 | { 79 | N = N_->j; 80 | int B[4][4] = { 81 | {geti(B_,"ore","ore"), 0, 0, 0}, 82 | {geti(B_,"cla","ore"), 0, 0, 0}, 83 | {geti(B_,"obs","ore"), geti(B_,"obs","cla"), 0, 0}, 84 | {geti(B_,"geo","ore"), 0, geti(B_,"geo","obs"), 0} 85 | }; 86 | int s[4] = {0,0,0,0}; 87 | int r[4] = {1,0,0,0}; 88 | int maxg=0; 89 | int re = f(B,&maxg,0,s,r); 90 | __builtin_printf("..%i..\n",re); 91 | R kj(re); 92 | } -------------------------------------------------------------------------------- /aoc/2022/q/19.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/19 2 | 3 | inp: read0`:input/19.txt 4 | 5 | //// https://github.com/adotsch/AOC 6 | // András Dőtsch 7 | 8 | I:("J"$" "vs/: inp)[;`ore`cla`obs`geo!((1#`ore)!1#6;(1#`ore)!1#12;`ore`cla!18 21;`ore`obs!27 30)] 9 | 10 | system"gcc -std=gnu99 -DKXVER=3 -O3 -fPIC -c 19.c"; 11 | system"gcc -shared -fPIC 19.o -o 19.so"; 12 | ff:`19 2:`ff,2 13 | 14 | \t show sum (1+til count I) * r: ff[24] peach I //1199 15 | \t show prd ff[32] peach 3#I //13*18*15 16 | 17 | //// #adventofcode 18 | // Péter Györök 19 | .d19.checkRecipe:{[mt;r] 20 | queue:enlist`time`b0`b1`b2`b3`m0`m1`m2`m3!@[9#0;1;:;1]; 21 | maxb0:max r 0 1 2 4; 22 | top:0; 23 | round:0; 24 | while[count queue; 25 | queue:update ub:m3+rmt*(b3+b3+rmt-1)%2 from update rmt:mt-time from queue; 26 | queue:update ptop:m3+rmt*b3 from queue; 27 | round+:1; 28 | top|:exec max ptop from queue; 29 | queue:delete from queue where ubb0t, b0b1t, b1b2t, b2b3t; 35 | queue:delete b0t,b1t,b2t,b3t from q0,q1,q2,q3; 36 | if[0mt; 40 | ]; 41 | ]; 42 | top}; 43 | d19:{[time;x]a:("J"$(" "vs/:x))except\:0N; 44 | .d19.checkRecipe[time] each a}; 45 | d19p1:{sum(1+til[count x])*d19[24;x]}; 46 | d19p2:{prd d19[32;3 sublist x]}; 47 | 48 | -------------------------------------------------------------------------------- /aoc/2022/q/20.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/20 2 | 3 | inp: read0`:input/20.txt 4 | 5 | //// https://github.com/adotsch/AOC 6 | // András Dőtsch 7 | 8 | I:"J"$inp 9 | //part 1 10 | N:count I 11 | f:{[is;x] 12 | j0:is?x; 13 | is0:(j0#is),(j0+1)_is; 14 | m:I[x] mod N-1; 15 | j1:1+mod[m+j0-1;N-1]; 16 | (j1#is0),x,j1 _is0 17 | } 18 | J:I til[N] f/ til N 19 | sum J (1000 2000 3000 + J?0) mod N //6640 20 | // part 2 21 | I*:811589153 22 | J:I til[N] f/ til[10*N] mod N 23 | sum J (1000 2000 3000 + J?0) mod N //11893839037215 24 | 25 | //// #adventofcode 26 | // Péter Györök 27 | .d20.move:{[b;i] 28 | c:count b; 29 | n:b[i]; 30 | op:n`p; 31 | np:op+n[`v]; 32 | if[not np within 1,c-1; 33 | np:((np-1) mod c-1)+1]; 34 | $[op<=np; 35 | b:update p-1 from b where p within (op+1;np); 36 | b:update p+1 from b where p within (np;op-1)]; 37 | b[i;`p]:np; 38 | b}; 39 | .d20.mix:{[b].d20.move/[b;til count b]}; 40 | d20:{[part;x] 41 | a:"J"$x; 42 | c:count a; 43 | b:([]p:til c;v:a*$[part=2;811589153;1]); 44 | b:.d20.mix/[$[part=2;10;1];b]; 45 | p0:exec first p from b where v=0; 46 | exec sum v from b where p in (p0+1000 2000 3000) mod c}; 47 | d20p1:{d20[1;x]}; 48 | d20p2:{d20[2;x]}; -------------------------------------------------------------------------------- /aoc/2022/q/21.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/21 2 | 3 | inp: read0`:input/21.txt 4 | 5 | //// k4 Topicbox 6 | // Igor Khorkov 7 | / part 1 8 | value each ssr/[;(": ";"/");("::";"%")]@'inp;`long$root 9 | 10 | //// https://github.com/adotsch/AOC 11 | // András Dőtsch 12 | //part 1 13 | (v:`$4#'i)set'0; 14 | I:ssr[;"/";"%"]@'inp 15 | f:{value@'I;`. v};f/[]; 16 | "j"$root 17 | //part 2 18 | `va`vb set' `$(" "vs I v?`root)1 3; 19 | I:I where not I like "humn*" 20 | F:{v set' 0;humn::x;f/[];get[va]-get vb} 21 | "j"${x - .1 * Fx % F[x+.1] - Fx:F x}/[0] //Newton–Raphson method 22 | 23 | //// #adventofcode 24 | // Péter Györök 25 | d21p1:{a:": "vs/:x; 26 | val:(`$a[;0])!"F"$a[;1]; 27 | op:raze{d:" "vs x 1;$[3=count d;enlist[`$x 0]!enlist(("+-*/"!(+;-;*;%))d[1;0]),`$d 0 2;()]}each a; 28 | val:{[op;val]val^:key[op]!value[op][;0].'val 1_/:value[op];val}[op]/[val]; 29 | val`root}; 30 | d21p2:{a:": "vs/:x; 31 | val:enlist[::]!enlist(); 32 | val,:(`$a[;0])!"F"$a[;1]; 33 | val[`humn]:`humn; 34 | op:raze{d:" "vs x 1;$[3=count d;enlist[`$x 0]!enlist(("+-*/"!(+;-;*;%))d[1;0]),`$d 0 2;()]}each a; 35 | op[`root;0]:(=); 36 | val:{[op;val]val,:key[op]!value[op][;0]{$[any -9h<>type each y;x,y;x . y]}'val 1_/:value[op];val}[op]/[val]; 37 | if[0h<>type val[`root;1]; val[`root;1 2]:val[`root;2 1]]; 38 | goalNum:val[`root;2]; 39 | goalOp:val[`root;1]; 40 | while[0h=type goalOp; 41 | $[-9h=type goalOp 2;[ 42 | goalNum:$[(%)=first goalOp; goalNum*goalOp[2]; 43 | (*)=first goalOp; goalNum%goalOp[2]; 44 | (+)=first goalOp; goalNum-goalOp[2]; 45 | (-)=first goalOp; goalNum+goalOp[2]]; 46 | goalOp:goalOp 1; 47 | ];[ 48 | goalNum:$[(%)=first goalOp; goalOp[1]%goalNum; 49 | (*)=first goalOp; goalNum%goalOp[1]; 50 | (+)=first goalOp; goalNum-goalOp[1]; 51 | (-)=first goalOp; goalOp[1]-goalNum]; 52 | goalOp:goalOp 2; 53 | ]]; 54 | ]; 55 | goalNum}; 56 | 57 | //// https://github.com/CillianReilly/AOC 58 | // Cillian Reilly 59 | \P 0 60 | npt:{first[x]!ssr[;"/";"%"]each last x}("S*";":")0:inp 61 | 62 | // part 1 63 | o:(10h in type each value@){key[x]set'value x:{$[any -7 -9h in type x;x;any -7 -9h in type @[value;x;x];value x;any all each -7 9h=\:type each{@[value;x;x]}each -2#parse x;value x;x]}each x;x}/npt 64 | o`root 65 | 66 | // part 2 67 | delete humn from`.; 68 | npt:{first[x]!trim ssr[;"/";"%"]each last x}("**";":")0:`21.txt 69 | npt:@[npt;"humn";:;"humn"] 70 | root:ssr[npt"root";"+";"="] 71 | f:{$[y~"humn";y;any y in .Q.a;"(",,[;")"]string[first p]sv .z.s[x;] each x string -2#p:parse y;y]} 72 | step:{eval raze undo[;y]0 1 cut@[last x;y;:;first x]} 73 | g:{,[;enlist x[1;i]]step[first[x],enlist t;]i:?[;0h]type each t:{@[eval;x;x]}each last x} 74 | 75 | undo:{ op:2 first/x; 76 | $[(%)~op; 77 | $[y=1;(*;last x);(%;last x)]; 78 | (-)~op; 79 | $[y=1;(+;last x);(-;last x)]; 80 | (+)~op; 81 | $[y=1;(-;last x);(-;reverse last x)]; 82 | (*)~op; 83 | $[y=1;(%;last x);(%;reverse last x)] 84 | ]} 85 | 86 | o:asc{parse@[string value@;x;x]}each"="vs -1_1_f[npt;root] 87 | {step[first[x],enlist t;]?[;`humn]t:{@[eval;x;x]}each last x}(not`humn in last@)g/o -------------------------------------------------------------------------------- /aoc/2022/q/23.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/23 2 | 3 | inp: read0`:input/23.txt 4 | 5 | //// #adventofcode 6 | // Péter Györök 7 | d23:{[part;x] 8 | map:"#"=x; 9 | round:0; 10 | moveDirs:(6 3 0;7 4 1;2 0 1;5 3 4); 11 | moveDeltas:(-1 0;1 0;0 -1;0 1); 12 | while[1b; 13 | round+:1; 14 | filler:enlist (2+count first map)#0b; 15 | mapp:filler,(0b,/:map,\:0b),filler; 16 | mapr:-1_raze -1 1 0 rotate\:/:-1 1 0 rotate/:\:mapp; //NW, SW, W, NE, SE, E, N, S 17 | noMove:0=sum mapr; 18 | pmv:3=sum each not[mapr] moveDirs; 19 | noMove:not[mapp] or noMove or 0=sum pmv; 20 | pmv2:(0N,/:-1+til 5)@'enlist[noMove],pmv; 21 | prop:^/[reverse pmv2]; 22 | propCoord:raze til[count prop],/:'where each prop>-1; 23 | propDir:prop ./:propCoord; 24 | propDest:propCoord+moveDeltas propDir; 25 | validDest:where propDest in where 1=count each group propDest; 26 | if[(part=2) and 0=count validDest; :round]; 27 | propCoord:propCoord validDest; 28 | propDest:propDest validDest; 29 | mapp:.[;;:;0b]/[mapp;propCoord]; 30 | mapp:.[;;:;1b]/[mapp;propDest]; 31 | while[0b=max first mapp; mapp:1_mapp]; 32 | while[0b=max last mapp; mapp:-1_mapp]; 33 | while[0b=max mapp[;0]; mapp:1_/:mapp]; 34 | while[0b=max mapp[;count[first mapp]-1]; mapp:-1_/:mapp]; 35 | map:mapp; 36 | moveDirs:1 rotate moveDirs; 37 | moveDeltas:1 rotate moveDeltas; 38 | if[(part=1) and round=10; 39 | :`long$sum sum not map; 40 | ]; 41 | ]; 42 | }; 43 | 44 | // András Dőtsch 45 | I:`y`x!/:raze til[count inp],/:'where@'"#"=inp 46 | m:{[t;dx;dy] select y+dy,x+dx from t} 47 | f:{[t;i] 48 | //can move n,s,w,e 49 | mn: t except m[t; 1; 1],m[t; 0; 1],m[t;-1; 1]; 50 | ms: t except m[t; 1;-1],m[t; 0;-1],m[t;-1;-1]; 51 | mw: t except m[t; 1; 1],m[t; 1; 0],m[t; 1;-1]; 52 | me: t except m[t;-1; 1],m[t;-1; 0],m[t;-1;-1]; 53 | done: mn inter ms inter mw inter me; 54 | //choosing direction in the right order 55 | mvs:i rotate (mn;ms;mw;me) except\: done; 56 | mvs[1]: mvs[1] except mvs[0]; 57 | mvs[2]: mvs[2] except mvs[0],mvs[1]; 58 | mvs[3]: mvs[3] except mvs[0],mvs[1],mvs[2]; 59 | mvs:neg[i] rotate mvs; 60 | mn: mvs 0; mnm: m[mn; 0;-1]; 61 | ms: mvs 1; msm: m[ms; 0; 1]; 62 | mw: mvs 2; mwm: m[mw;-1; 0]; 63 | me: mvs 3; mem: m[me; 1; 0]; 64 | //can move unless others want to go there 65 | mn: mn except m[ msm,mwm,mem; 0; 1]; 66 | ms: ms except m[mnm ,mwm,mem; 0;-1]; 67 | mw: mw except m[mnm,msm ,mem; 1; 0]; 68 | me: me except m[mnm,msm,mwm ;-1; 0]; 69 | //move 70 | :raze( 71 | t except mn,ms,mw,me; 72 | m[mn; 0;-1]; 73 | m[ms; 0; 1]; 74 | m[mw;-1; 0]; 75 | m[me; 1; 0]) 76 | } 77 | 78 | {prd[1+max[x]-min x]-count x} I f/ til 10 79 | i:0;{i+::1;f[x;i-1]}/[I];i 80 | 81 | //// #vector-dojo 82 | // Rory Kemp 83 | elves:asc flip {(count first x) vs where raze x}"#"=read0 `23.txt 84 | dirs:`SE`S`SW`E`Z`W`NE`N`NW!{x cross x}1 0 -1 85 | adj:`N`S`W`E`Z!dirs(`N`NW`NE;`S`SW`SE;`W`NW`SW;`E`NE`SE;key[dirs]except `Z) 86 | L:10000; elves:L sv'5000+elves; dirs:L sv'dirs; adj:L sv''adj 87 | d:`E`N`S`W 88 | upd:{ 89 | n:{dirs x 0^{first where all each x} each not in[;y] y +\: adj x}[`Z,d::1 rotate d; x]; 90 | asc x+n*1={(count each group x)x}x+n} 91 | ({(prd 1+max[x]-min x)-count x}flip L vs r 10; count r:upd scan elves) 92 | 93 | 94 | -------------------------------------------------------------------------------- /aoc/2022/q/24.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/24 2 | 3 | inp: read0`:input/24.txt 4 | 5 | //// #adventofcode 6 | // Péter Györök 7 | d24:{[part;x] 8 | w:count first x; h:count x; 9 | mapbase:".#"x="#"; //for visual only 10 | s:0,first where"."=first x; 11 | t:(count[x]-1),first where"."=last x; 12 | bdirm:">v<^"?x; 13 | bpos:raze til[count x],/:'where each 4>bdirm; 14 | bdir:bdirm ./:bpos; 15 | moves:(0 1;1 0;0 -1;-1 0;0 0); 16 | squeue:$[part=1;enlist s;(s;t;s)]; 17 | tqueue:$[part=1;enlist t;(t;s;t)]; 18 | round:0; 19 | while[count squeue; 20 | s:first squeue; t:first tqueue; 21 | squeue:1_squeue; tqueue:1_tqueue; 22 | queue:enlist s; 23 | found:0b; 24 | while[not found; 25 | if[0=count queue; '"no solution?!"]; 26 | round+:1; 27 | bpos+:moves bdir; 28 | bpos[where bpos[;0]=0;0]:h-2; 29 | bpos[where bpos[;1]=0;1]:w-2; 30 | bpos[where bpos[;0]=h-1;0]:1; 31 | bpos[where bpos[;1]=w-1;1]:1; 32 | dbpos:distinct bpos; 33 | queue:distinct raze queue+/:\:moves; 34 | queue:queue except dbpos; 35 | queue:queue where all each queue within\:(0 0;(h-1;w-1)); 36 | queue:queue where "#"<>x ./:queue; 37 | if[1b; //set to 1b to enable visual 38 | map:mapbase; 39 | map:.[;;:;]/[map;bpos;">v<^"bdir]; 40 | gbpos:{(where 1v<^"!(1 0;0 1;-1 0;0 -1) 53 | sx:count[inp 0]-2;sy:count[inp]-2; 54 | c:sx*1+first where 0=mod[sx*1+til sy;sy] 55 | M:c#enlist("#><^v."!"#.....")inp 56 | f:{ 57 | t:i[y;x]; 58 | $[t in "#.";();[ 59 | xs:1+mod[(x-1)+d[t;0]*til c;sx]; 60 | ys:1+mod[(y-1)+d[t;1]*til c;sy]; 61 | .[`M;;:;"#"]@'til[c],'ys,'xs 62 | ]] 63 | } 64 | .[f] each cross[1+til sx;1+til sy]; 65 | F:{[j;T] 66 | T:distinct T,update x:x mod(sx+2),y:y mod(sy+2) from raze( 67 | update x-1 from T; update x+1 from T; 68 | update y-1 from T; update y+1 from T); 69 | (j+1;delete from T where "#"=M[j mod c]'[y;x]) 70 | } 71 | r1: -1 + first .[{not (sx;sy+1) in y}] .[F]/ ( 0;enlist`x`y!1 0) 72 | show r1 //part 1 73 | r21: -1 + first .[{not ( 1; 0) in y}] .[F]/ ( r1;enlist`x`y!(sx;sy+1)) 74 | r2: -1 + first .[{not (sx;sy+1) in y}] .[F]/ (r21;enlist`x`y!1 0) 75 | show r2 //part 2 76 | 77 | 78 | -------------------------------------------------------------------------------- /aoc/2022/q/25.q: -------------------------------------------------------------------------------- 1 | /https://adventofcode.com/2022/day/25 2 | 3 | inp: read0`:input/25.txt 4 | 5 | //// #adventofcode 6 | // Péter Györök 7 | d25:{digits:("=-012"!-2+til 5); 8 | s:5 vs sum 5 sv/:digits x; 9 | digits?{[s]if[first[s]>2; s:0,s];s+next[s>2]+(s>2)*-5}/[s]}; 10 | 11 | // András Dőtsch 12 | f:{x[i:where 2 The Great Way is not difficult. It avoids only picking and choosing. 8 | 9 | The [Do form of the Scan iterator](https://code.kx.com/q/ref/accumulators/#do) has a pattern I think of as ‘the Zen monks’. 10 | 11 | ![](img/lightbulb-wide.png) 12 | 13 | * How many Zen monks does it take to change a lightbulb? 14 | * Two. One to change it; one not to change it. 15 | 16 | The basic pattern is to apply a function and not to apply it. Consider the `trim` keyword. It must find the spaces in a string, then the continuous spaces from each end. If we had to write `trim` in q it might be 17 | 18 | ```q 19 | q){b:x<>" ";(b?1b)_ neg[reverse[b]?1b] _ x}" Trim the spaces. " 20 | "Trim the spaces." 21 | ``` 22 | 23 | We notice the repetitions: 24 | 25 | * both `b` and `reverse[b]` are searched for `1b` 26 | * two uses of the Drop operator 27 | 28 | We want to do the search/drop thing from both ends of the string. 29 | 30 | ```q 31 | q){x{y _ x}/1 -1*(1 reverse\" "<>x)?'1b}" Trim the spaces. " 32 | "Trim the spaces." 33 | ``` 34 | 35 | Notice the `{y _ x}` reduction above. Lambda `{y f x}` commutes a function `f` by switching its arguments. The pattern `R{y f x}/L` successively applies a list of left arguments `L` to an argument `R`. 36 | 37 | Here we use `1 reverse\` to get the boolean vector and its reversal. I think of this `1 f\` pattern as the Zen monks. 38 | Here is another use for it, in finding the shape (rows and columns) of a matrix. 39 | 40 | ```q 41 | q)show m:{max[count each x]$'x}string`avoids`picking`and`choosing 42 | "avoids " 43 | "picking " 44 | "and " 45 | "choosing" 46 | q)shp:{count each 1 first\x} / shape of a matrix 47 | q)shp m 48 | 4 8 49 | ``` 50 | 51 | The Zen Buddhist pension plan: 52 | 53 | > A day without work is a day without food. 54 | 55 | Can you see any other work for the monks? -------------------------------------------------------------------------------- /euler/01.md: -------------------------------------------------------------------------------- 1 | # 1. Multiples of 3 or 5 2 | 3 | ## Problem 4 | 5 | If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 6 | 7 | Find the sum of all the multiples of 3 or 5 below 1000. 8 | 9 | 10 | ## Solution 1 11 | 12 | ```q 13 | q)til 1000 / numbers below 1000 14 | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 .. 15 | q)(til 1000)mod/:3 5 / their 3- and 5- moduli 16 | 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2.. 17 | 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3.. 18 | q)not min(til 1000)mod/:3 5 / min finds the zeros 19 | 10010110011010010010110011010010010110011010010010110011010010010110011010010.. 20 | q)where not min(til 1000)mod/:3 5 21 | 0 3 5 6 9 10 12 15 18 20 21 24 25 27 30 33 35 36 39 40 42 45 48 50 51 54 55 5.. 22 | ``` 23 | ```q 24 | sum where not min(til 1000)mod/:3 5 25 | ``` 26 | 27 | ## Solution 2 28 | 29 | But we don’t need to do all that arithmetic. 30 | 31 | ```q 32 | q)\t:10000 sum where not min(til 1000)mod/:3 5 33 | 112 34 | q)\t:10000 sum where 0b,999#max 15#'(001b;00001b) 35 | 17 36 | ``` 37 | 38 | ## Solution 3 39 | 40 | On [community.kx.com](https://community.kx.com/t5/kdb-and-q/Q-For-Problems-Episode-1/m-p/13090) jkane17 uses an arithmetic series for the sums of numbers at fixed intervals. 41 | 42 | $$ S_n = n * (a + a_n)/2$$ 43 | $$ a_n = a + d * (n-1)$$ 44 | 45 | to calculate the sums of multiples of 3, 5 and 15. 46 | The answer is the sums of the series for 3 and 5, less the sum of the series for their product, 15: 47 | 48 | ```q 49 | sum .5*n*a*1+n:floor 999%a:3 5 -15 50 | ``` 51 | 52 | For the numbers to 1000, the advantage over Solution 2 is slight, but increases for higher values of `n`. 53 | 54 | ```q 55 | q)\t:10000 sum .5*n*a*1+n:floor 999%a:3 5 -15 56 | 14 57 | 58 | q)\t:10000 sum where 0b,99999#max 15#'(001b;00001b) 59 | 554 60 | q)\t:10000 sum .5*n*a*1+n:floor 99999%a:3 5 -15 61 | 12 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /euler/02.md: -------------------------------------------------------------------------------- 1 | # 2. Even Fibonacci numbers 2 | 3 | ## Problem 4 | 5 | Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 6 | 7 | 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 8 | 9 | By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. 10 | 11 | 12 | ## Solution 1 13 | 14 | On [community.kx.com](https://community.kx.com/t5/kdb-and-q/Q-For-Problems-Episode-2/td-p/13148) jkane17 offers 15 | 16 | ```q 17 | q)fib:{x,sum -2#x}/[;1 2] 18 | q)fib 10 19 | 1 2 3 5 8 13 21 34 55 89 144 233 20 | ``` 21 | 22 | The definition of `fib` exploits the rule that the Over iterator applied to a function `f` derives a variadic function `f/`. Projecting that on `[;0 1]` ensures the binary form of `f/` is projected. The resulting unary will be the [Do](https://code.kx.com/q/ref/accumulators/#do) or [While](https://code.kx.com/q/ref/accumulators/#while) form of Over, depending on the argument it is applied to. Above, applied to 10, it is the Do form. Applied to a test function, it is the While form: 23 | 24 | ```q 25 | q)fib {x>last y}[4000000] 26 | 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 .. 27 | ``` 28 | This ends with the first Fibonacci number to exceed 4,000,000. 29 | 30 | ```q 31 | q)-5#fib {x>last y}[4000000] 32 | 832040 1346269 2178309 3524578 5702887 33 | ``` 34 | 35 | So we need to `-1_` to drop the last term. 36 | 37 | We can find the even numbers with `mod 2`. 38 | 39 | ```q 40 | sum{x where not x mod 2} -1 _ fib {x>last y}[4000000] 41 | ``` 42 | 43 | 44 | ## Solution 2 45 | 46 | The projection used as a truth function could be written as a composition: 47 | 48 | ```q 49 | sum{x where not x mod 2} -1 _ fib (4000000>last@) 50 | ``` 51 | 52 | And the arithmetic of `mod` can be replaced by selecting every third item. 53 | 54 | ```q 55 | sum{x where count[x]#001b}0, -1 _ fib (4000000>last@) 56 | ``` 57 | 58 | But with only 34 Fibonacci numbers under 4 million, there is no significant advantage. 59 | 60 | 61 | ## Solution 3 62 | 63 | It's also possible to directly compute the n-th Fibonacci number using the golden ratio. Since every third Fibonacci number is even, we can just calculate those directly. 64 | 65 | ```q 66 | phi:1(1-)\0.5*1+s5:sqrt 5 / Phi, 1-Phi 67 | fibn:reciprocal[s5]* .[-] (phi xexp) @ 68 | sum -1_ (4000000>last@) {x,fibn 3*count x}/0f 69 | ``` 70 | -------------------------------------------------------------------------------- /euler/03.md: -------------------------------------------------------------------------------- 1 | # 3. Largest prime factor 2 | 3 | ## Problem 4 | 5 | https://projecteuler.net/problem=3 6 | 7 | The prime factors of 13195 are 5, 7, 13 and 29. 8 | What is the largest prime factor of the number 600851475143? 9 | 10 | ## Solution 11 | 12 | Candidate prime factors are the primes to the square root of 600851475143. 13 | 14 | We apply Erastosthenes’ Sieve. 15 | (See [Finding primes](../essays/findingprimes.md).) 16 | 17 | ```q 18 | N:600851475143 19 | /candidates: primes to √N 20 | kc:{(1#2;0b,1_x#10b)} / known primes; flag candidates 21 | snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. / sieve next prime 22 | es:raze@[;1;1+where@] {{x>last first y}[floor sqrt x] snp/kc x}@ / Eratosthenes' sieve 23 | c:es floor sqrt N / primes to √N 24 | 25 | last c where not N mod c / overcompute: try all 26 | ``` 27 | 28 | It remains to find the largest that is a factor of `N`. 29 | 30 | ```q 31 | last c where not N mod c 32 | ``` 33 | 34 | ## Loop? 35 | 36 | The solution above is an example of ‘overcomputing’ typical of vector solutions. 37 | It computes `N mod` for every candidate. 38 | Instead we could stop after the first zero result. 39 | 40 | ```q 41 | .[@] ({x mod y z}[N].) @[;1;1+]/(c;0) 42 | ``` 43 | 44 | In pseudocode: 45 | 46 | ```txt 47 | i = 0 48 | while mod[N;c[i]] 49 | i++ 50 | endwhile 51 | return c[i] 52 | ``` 53 | 54 | The initial state is `(c;0)` – the candidates and the first index to try. 55 | The function `@[;1;1+]` is a unary projection of [Index At](https://code.kx.com/q/ref/apply#index-at). 56 | It simply increments the index. 57 | It is applied in the While form of the Over iterator; the truth function computes the modulo, and iteration stops when it returns zero. 58 | 59 | The final `.[@]` returns the indexed item of `c`. 60 | 61 | But if we’re going to loop, we might as well lean into it and use the `while` keyword. 62 | 63 | ```q 64 | i:count c; while[N mod c i-:1;]; c i 65 | ``` 66 | 67 | Did that help? Is the explicit While loop ‘paid for’ by the reduction in modulo computations? 68 | 69 | Not in this case, because the largest prime factor comes low in the list of candidates. 70 | The efficiency of implicit iteration justifies the overcompute. 71 | 72 | ```q 73 | q)\t:10 last c where not N mod c 74 | 3 75 | q)\t:10 i:count c; while[N mod c i-:1;]; c i 76 | 489 77 | ``` 78 | 79 | ## Edge case 80 | 81 | What if `N` is prime? Then it must be the last factor tried: 82 | 83 | ```q 84 | C:N,c 85 | last {x where not N mod x} C / vector 86 | i:count C; while[N mod C i-:1;]; C i / While loop 87 | ``` 88 | -------------------------------------------------------------------------------- /euler/03.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=3 2 | /The prime factors of 13195 are 5, 7, 13 and 29. 3 | /What is the largest prime factor of the number 600851475143 ? 4 | 5 | /N:13195 6 | N:600851475143 7 | 8 | /candidates: primes to √N 9 | kc:{(1#2;0b,1_x#10b)} / known primes; flag candidates 10 | snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. / sieve next prime 11 | es:raze@[;1;1+where@] {{x>last first y}[floor sqrt x] snp/kc x}@ / Eratosthenes' sieve 12 | c:es floor sqrt N / primes to √N 13 | 14 | last c where not N mod c / overcompute: try all 15 | 16 | 17 | \ 18 | i:count[c]-1; while[N mod c i-:1;]; c i 19 | .[@] ({z and x mod y z}[N].) @[;1;-1+]/(c;count c) / loop to find last 20 | -------------------------------------------------------------------------------- /euler/04.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=4 2 | /A palindromic number reads the same both ways. 3 | /The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99. 4 | /Find the largest palindrome made from the product of two 3-digit numbers. 5 | 6 | c:prd each distinct asc each {x cross x} 1 _ til 1000 / candidate products 7 | ip:{x~reverse x} / is palindrome? 8 | 9 | / Solution 1 10 | max c where ip each string c 11 | i:count C:asc c; while[not ip string C i-:1;]; C i 12 | /.[@]({not{x~reverse x}string x@y}.) @[;1;-1+]/(asc c;count[c]-1) 13 | lastitem:{[test;list].[@] ({x y z}[test].) @[;1;-1+]/ (list;-1+count list)} 14 | lastitem[not ip string@] asc c 15 | 16 | 17 | / Solution 2 18 | sol2:{ 19 | // Create all palindromes in reverse order 20 | digits:reverse string til 10; 21 | palindromes:{[x;y;z]raze x,/:'y,\:/:x}[digits]/[;til x-1]; 22 | pals:"J"$palindromes 2#/:digits; 23 | 24 | // create all x-digit numbers 25 | nums:reverse r[1]+til(-/)r:`long$10 xexp 0 -1+x; 26 | 27 | // Recursively check each palindrome, early exit if found 28 | {[pals;nums] 29 | p:first pals; 30 | b:and[first[nums]>n]not mod[;1]n:p%nums mod[p;nums]?0; 31 | $[b;p;.z.s[1_pals;nums]] 32 | }[pals;nums] 33 | } 34 | -------------------------------------------------------------------------------- /euler/05.md: -------------------------------------------------------------------------------- 1 | # 5. Smallest multiple 2 | 3 | https://projecteuler.net/problem=5 4 | 5 | 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. 6 | What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20? 7 | 8 | 9 | # Solve 10 | 11 | Start by reproducing the example. 12 | 10 is the smallest candidate. 13 | Start with 10 and keep incrementing; as long as any `mod 1+til 10` 14 | 15 | A while-loop will do the job. 16 | 17 | ```q 18 | q)f:1+til 10; i:10; while[any i mod f; i+:1]; i 19 | 2520 20 | ``` 21 | 22 | We can write the same in functional form using the [While form of the Over iterator](https://code.kx.com/q/ref/accumulators/#while), with a composition as the truth function. 23 | 24 | ```q 25 | q)(any mod[;1+til 10]@) (1+)/10 26 | 2520 27 | ``` 28 | 29 | ## Improve 30 | 31 | But we *don’t* need to test every number. 32 | A number evenly divisible by `1+til 10` must be evenly divisible by each of the primes in that list, i.e. `2 3 5 7`, and must therefore be divisible by their product `P`. 33 | We can start with `P`, and test multiples of it. 34 | 35 | ```q 36 | q)(any mod[;1+til 10]@) (P+)/P:prd 2 3 5 7 37 | 2520 38 | 39 | q)\ts:100 (any mod[;1+til 10]@) (1+)/10 40 | 239 2064 41 | q)\ts:100 (any mod[;1+til 10]@) (P+)/P:prd 2 3 5 7 42 | 1 2848 43 | ``` 44 | 45 | With the numbers from 1 to 20, `P` becomes 9699690, and the search takes very little longer. 46 | 47 | ```q 48 | q)\ts:100 (any mod[;1+til 20]@) (P+)/P:prd 2 3 5 7 11 13 17 19 49 | 3 3168 50 | ``` 51 | 52 | ## Generalise 53 | 54 | For a number `N` we need the primes below it. 55 | Enter [Eratosthenes’ Sieve](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes). 56 | 57 | ![Sieve of Eratosthenes](Sieve_of_Eratosthenes_animation.gif) 58 | 59 | ```q 60 | kc:{(1#2;0b,1_x#10b)} / (known primes; flag candidates) 61 | snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. / sieve next prime 62 | es:raze@[;1;1+where@] {{x>last first y}[floor sqrt x] snp/kc x}@ / Eratosthenes' sieve 63 | ``` 64 | 65 | ```q 66 | q){(any mod[;1+til x]@) (P+)/P:prd es x}10 67 | 2520 68 | ``` 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /euler/05.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=5 2 | / 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. 3 | /What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20? 4 | 5 | {any 0 The sum of the squares of the first ten natural numbers is 385. 6 | > The square of the sum of the first ten natural numbers is 3025. 7 | > Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 8 | > 3025 − 385 = 2640 . 9 | > 10 | > Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum. 11 | 12 | 13 | ## Solutions 14 | 15 | This is close to trivial in q. 16 | 17 | ```q 18 | nnt:1+til:: / natural numbers to x 19 | sqr:{x*x} 20 | {(sqr sum x)-sum sqr x} nnt 100 21 | ``` 22 | 23 | ## Alternatives 24 | 25 | We can explore some alternatives. 26 | 27 | Faster: drop `nnt` and `sqr` (and any prejudice against overwriting the argument). 28 | 29 | ```q 30 | {(x*x:sum x)-sum x*x} 1+til 100 31 | ``` 32 | 33 | The square of the sums, the sum of the squares – two compositions? 34 | 35 | ```q 36 | (-).(sqr sum@;sum sqr@)@\:nnt 100 37 | ``` 38 | 39 | We can factor out the repetitions. 40 | The Zen monks will give us `sqr` and `sum` both reversed and not; `1 reverse\(sqr;sum)`, a 2×2 matrix. 41 | 42 | ```q 43 | q)1 reverse\(sqr;sum) 44 | {x*x} sum 45 | sum {x*x} 46 | ``` 47 | 48 | [Compose](https://code.kx.com/q/ref/compose) `'[;]` is binary (composes two functions) so can be applied by Apply Each Right `./:` to each row of the matrix to produce the two compositions. 49 | 50 | ```q 51 | q)'[;]./:1 reverse\(sqr;sum) 52 | {x*x}sum 53 | sum{x*x} 54 | ``` 55 | 56 | It remains only to Apply At Each Left `@\:` the compositions to the vector and take the difference. 57 | 58 | ```q 59 | .[-] ('[;] ./: 1 reverse\(sqr;sum) ) @\: nnt 100 60 | ``` 61 | 62 | Composition rocks – and opens the way for cases where the functions (here `sqr` and `sum`) are determined at runtime. 63 | 64 | Improving readability here… not so much. 65 |
66 | 67 | ### Constant time solution 68 | 69 | The sum of first n natural numbers is given by 70 | 71 | $$ 72 | S_n = n * ( n + 1 ) / 2 73 | $$ 74 |
75 | 76 | ```q 77 | // Sum of the first x positive integers 78 | nsum:{"j"$.5*x*x+1} 79 | ``` 80 |
81 | 82 | The sum of the first n squares is given by 83 | 84 | $$ 85 | S_{n^2} = n * ( 2n + 1 )( n + 1 ) / 6 86 | $$ 87 |
88 | 89 | ```q 90 | // Sum of the squares of the first x positive integers 91 | n2sum:{div[x*(1+2*x)*x+1;6]} 92 | ``` 93 |
94 | 95 | ```q 96 | {(prd 2#nsum x)-n2sum x} 100 97 | ``` 98 | 99 | --- 100 | 101 | Contributors 102 | 103 | * Nick Psaris 104 | * Stephen Taylor 105 | * Alex Unterrainer 106 | * Jonathan Kane 107 | -------------------------------------------------------------------------------- /euler/06.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=6 2 | /The sum of the squares of the first ten natural numbers is 385 3 | /The square of the sum of the first ten natural numbers is 3025 4 | / Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 5 | / 3025 − 385 = 2640 6 | / Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum. 7 | 8 | / solutions 9 | / nnt:1+til@ / natural numbers to 10 | nnt:1+til:: / natural numbers to 11 | sqr:{x*x} 12 | {(sqr sum x)-sum sqr x} nnt 100 13 | 14 | / Constant time solution 15 | nsum:{"j"$.5*x*x+1} / Sum of the first x positive integers 16 | n2sum:{div[x*(1+2*x)*x+1;6]} / Sum of the squares of the first x positive integers 17 | {(prd 2#nsum x)-n2sum x} 100 18 | 19 | / 20 | .[-](sqr sum@;sum sqr@)@\: nnt 100 21 | .[-]('[sqr;sum];'[sum;sqr])@\: nnt 100 22 | .[-]('[;]./:1 reverse\(sqr;sum))@\:nnt 100 23 | k).[-]('[;]./:1|:\(sqr;sum))@\:nnt 100 24 | 25 | // Nick Psaris 26 | though less well-known, i prefer to build compositions with :: instead of @. 27 | @ adds an extra operator in the train of functions: 28 | q)1+til@ 29 | +[1]@[k){$[0>@x;!x;'`type]}] 30 | q)1+til:: 31 | +[1]k){$[0>@x;!x;'`type]} 32 | your solution introduces many new concepts. but as you indicate, it reduces readability. 33 | a shorter, faster and more readable solution would be: 34 | ssd:{(x*x:sum x)-sum x*x:1+til x} / sum square difference 35 | -------------------------------------------------------------------------------- /euler/07.md: -------------------------------------------------------------------------------- 1 | # 10001st prime 2 | 3 | https://projecteuler.net/problem=7 4 | 5 | > By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 6 | > 7 | > What is the 10,001st prime number? 8 | 9 | 10 | ## Solution 1 11 | 12 | Use Eratosthenes’ Sieve to generate enough primes. Then pick the 10,001st. 13 | 14 | The Sieve: start with an initial state of known primes (2) and a vector flagging the (odd) numbers still to test. 15 | 16 | Here it is in slo-mo. 17 | 18 | ![Sieve of Eratosthenes animation: SKopp at German Wikipedia, CC BY-SA 3.0 , via Wikimedia Commons](Sieve_of_Eratosthenes_animation.gif) 19 | 20 | And in code: 21 | 22 | ```q 23 | q)kc:{(1#2;0b,1_x#10b)} / (known primes; flag candidates) 24 | q)kc 20 25 | ,2 26 | 00101010101010101010b 27 | ``` 28 | 29 | The step function: sieve the next prime. 30 | It’s the first number flagged. Join it to the known primes and remove its multiples from the flag vector. 31 | 32 | ```q 33 | q)snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. / sieve next prime 34 | q)snp kc 20 35 | 2 3 36 | 00001010001010001010b 37 | ``` 38 | 39 | Sieve the initial state to get all the primes under a million. (Surely enough?) 40 | 41 | ```q 42 | q)es:{{x>last first y}[floor sqrt x] snp/kc x} / Eratosthenes' Sieve 43 | q)es 50 44 | 2 3 5 7 45 | 00000000001010001010001000001010000010001010001000b 46 | q)rslv:raze @[;1;1+where@]@ / resolve result 47 | q)rslv es 50 48 | 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 49 | q)pt:rslv es@ / primes to 50 | q)pt 50 51 | 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 52 | ``` 53 | 54 | ## Solution 2 55 | 56 | The [While form of the Over iterator](https://code.kx.com/q/ref/accumulators/#while) here uses a test function that stops when candidates exceed $\sqrt{N}$. 57 | All the remaining flags then mark primes, and we know that we have sieved out all the primes below $N$. 58 | 59 | But until then we do not know how many of the remaining flags mark primes. 60 | The first item of the state lists the primes we have found. 61 | 62 | If we examine the intermediate result of sieving for primes below a million, we see there have been 168 iterations. 63 | 64 | ```q 65 | q)count first es 1000000 / # iterations 66 | 169 67 | ``` 68 | 69 | Sieving for primes below a million was a lucky guess. Is there a lower $N$ we could use? 70 | 71 | By convention $\pi(x)$ denotes the number of primes below $x$. 72 | Its values have been calculated for powers of 10. 73 | 74 | ```q 75 | PI:0 4 25 168 1229 9592 78498 664579 5761455 50487534 455052511 4118054813 37607912018 346065536839 76 | ``` 77 | 78 | This tells us that to get 10,001 primes the lowest power of 10 to use for $N$ is $10^6$. 79 | 80 | ```q 81 | q)sum PI<10001 82 | 6i 83 | q)count pt "j"$10 xexp sum PI<10001 84 | 78498 85 | ``` 86 | 87 | We have replaced a lucky guess with a reasoned approximation. 88 | But it’s still the same number of iterations, and seven times as many primes as we need. 89 | 90 | ## Solution 3 91 | 92 | The [Prime Number Theorem](https://primes.utm.edu/howmany.html) tells us that 93 | 94 | $$\pi(x) \approx x \div \ln(x)$$ 95 | 96 | What value of $x$ gives us $\pi(x)>10000$? 97 | 98 | Let’s look. Start with 1000 and, instead of going up in orders of magnitude, keep doubling. 99 | 100 | ```q 101 | pi:{x%log x} / π(x) first approximation 102 | q)(10000>pi@)(2*)/1000 103 | 128000 104 | q)pi 128000 105 | 10884.55 106 | q)count pt (10000>pi@)(2*)/1000 107 | 11987 108 | ``` 109 | 110 | We could refine the search to find a lower value of $N$ but it is unlikely to reduce the number of iterations by much. 111 | 112 | ```q 113 | q)count first es 128000 / # iterations 114 | 72 115 | ``` 116 | 117 | ## Comments 118 | 119 | This is a nice example of using q in the REPL not only to find a solution but to explore how to improve it. 120 | 121 | ```q 122 | kc:{(1#2;0b,1_x#10b)} / (known primes; flag candidates) 123 | snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. / sieve next prime 124 | es:{{x>last first y}[floor sqrt x] snp/kc x} / Eratosthenes' Sieve 125 | rslv:raze @[;1;1+where@]@ / resolve result 126 | pt:rslv es@ / primes to 127 | pi:{x%log x} / π(x) first approximation 128 | 129 | p:pt (10000>pi@)(2*)/1000 / first 10000 or so primes 130 | p@10000 / 10001st prime 131 | ``` 132 | 133 | --- 134 | 135 | Contributors 136 | 137 | * Stephen Taylor -------------------------------------------------------------------------------- /euler/07.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=7 2 | / By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 3 | / What is the 10 001st prime number? 4 | 5 | kc:{(1#2;0b,1_x#10b)} / (known primes; flag candidates) 6 | snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. / sieve next prime 7 | es:{{x>last first y}[floor sqrt x] snp/kc x} / Eratosthenes' Sieve 8 | rslv:raze @[;1;1+where@]:: / resolve result 9 | pt:rslv es:: / primes to 10 | pi:{x%log x} / π(x) first approximation 11 | 12 | p:pt (10000>pi::)(2*)/1000 / first 10000 or so primes 13 | p@10000 / 10001st prime 14 | 15 | / Nth primes 16 | np:{[n] @[;n] pt (n>pi@)(2*)/1000 } -------------------------------------------------------------------------------- /euler/07a.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=7 2 | / By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 3 | / What is the 10 001st prime number? 4 | np1:{[n] / nth prime 5 | es:{ / Eratosthenes' Sieve 6 | kc:{(1#2;0b,1_x#10b)}; / (known primes; flag candidates) 7 | snp:{i:(n-1)+n*til count[y]div n:1+i:y?1b;(x,n;@[y;i;:;0b])}. ; / sieve next prime 8 | {x>last first y}[floor sqrt x] snp/kc x }; 9 | rslv:raze @[;1;1+where@]::; / resolve result 10 | pt:rslv es::; / primes to 11 | pi:{x%log x}; / π(x) first approximation 12 | @[;n]pt (n>pi@)(2*)/1000 } 13 | 14 | np0: {[N] / Nth prime 15 | P: (N>{x%log x}::)(2*)/1000; / Nth prime < P:π(x) first approx 16 | es: { / Eratosthenes' Sieve for primes til p:1+i:f?1b)}[x].; / sieve next prime 19 | {x>last first y}[floor sqrt x] snp/kf x }; / stop at √x 20 | @[;N] raze @[;1;1+where::] es P } 21 | 22 | 23 | np2:{[n] / nth prime 24 | es:{ / Eratosthenes' Sieve 25 | kc:{(1#2;0b,1_x#10b)}; / (known primes; flag candidates) 26 | snp:{(x,n;y&count[y]#i<>til n:1+i:y?1b)}. ; / sieve next prime 27 | {x>last first y}[floor sqrt x] snp/kc x }; 28 | rslv:raze @[;1;1+where@]::; / resolve result 29 | pt:rslv es::; / primes to 30 | pi:{x%log x}; / π(x) first approximation 31 | @[;n]pt (n>pi@)(2*)/1000 } 32 | 33 | / Jonathan Kane 34 | // Check if a number prime 35 | .math.isPrime:{$[ 36 | 0)(6+)\ 6 41 | ]} 42 | 43 | nprimes3:{@[;x-1]last(x>count last@){(x[0]+:1;x[1],n where .math.isPrime n:-1 1+6*x 0)}/(1;2 3)} 44 | 45 | nprimes4:{[N] / Nth prime 46 | is:("i"$1,count::;.math.isPrime;::)@\:2 3; / initial state: k:1; 2 3 found 47 | step:{[x;y;z] 48 | b:.math.isPrime n:-1 1+6*first x; / test 2 candidates 49 | (x+1,sum b;b;n) / new state 50 | }.; 51 | fs:{x>y . 0 1}[N;] step/is; / final state 52 | {[n;kc;b;p] (p where b)@(kc 1)-n}[N;;;] . fs } 53 | 54 | / nprimes4:{ 55 | / {[n;kc;b;p] p where b) (kc 1)-n}[x;;;] . 56 | / {x>y . 0 1}[x;] 57 | / ({[x;y;z] b:.math.isPrime n:-1 1+6*first x; (x+1,sum"j"$b;b;n) }.)/ (1 2;11b;2 3) 58 | / } 59 | 60 | \ 61 | q)\ts nprimes3 10001 62 | 365 262784 63 | q)\ts nprimes4 10001 64 | 349 5088 -------------------------------------------------------------------------------- /euler/08.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=8 2 | /The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832. 3 | 4 | / 73167176531330624919225119674426574742355349194934 5 | / 96983520312774506326239578318016984801869478851843 6 | / 85861560789112949495459501737958331952853208805511 7 | / 12540698747158523863050715693290963295227443043557 8 | / 66896648950445244523161731856403098711121722383113 9 | / 62229893423380308135336276614282806444486645238749 10 | / 30358907296290491560440772390713810515859307960866 11 | / 70172427121883998797908792274921901699720888093776 12 | / 65727333001053367881220235421809751254540594752243 13 | / 52584907711670556013604839586446706324415722155397 14 | / 53697817977846174064955149290862569321978468622482 15 | / 83972241375657056057490261407972968652414535100474 16 | / 82166370484403199890008895243450658541227588666881 17 | / 16427171479924442928230863465674813919123162824586 18 | / 17866458359124566529476545682848912883142607690042 19 | / 24219022671055626321111109370544217506941658960408 20 | / 07198403850962455444362981230987879927244284909188 21 | / 84580156166097919133875499200524063689912560717606 22 | / 05886116467109405077541002256983155200055935729725 23 | / 71636269561882670428252483600823257530420752963450 24 | 25 | / Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product? 26 | 27 | 28 | n:"J"$'raze read0`:08.txt 29 | max prd each n {til[y]+/:til x-y-1}[count n;13] 30 | -------------------------------------------------------------------------------- /euler/08.txt: -------------------------------------------------------------------------------- 1 | 73167176531330624919225119674426574742355349194934 2 | 96983520312774506326239578318016984801869478851843 3 | 85861560789112949495459501737958331952853208805511 4 | 12540698747158523863050715693290963295227443043557 5 | 66896648950445244523161731856403098711121722383113 6 | 62229893423380308135336276614282806444486645238749 7 | 30358907296290491560440772390713810515859307960866 8 | 70172427121883998797908792274921901699720888093776 9 | 65727333001053367881220235421809751254540594752243 10 | 52584907711670556013604839586446706324415722155397 11 | 53697817977846174064955149290862569321978468622482 12 | 83972241375657056057490261407972968652414535100474 13 | 82166370484403199890008895243450658541227588666881 14 | 16427171479924442928230863465674813919123162824586 15 | 17866458359124566529476545682848912883142607690042 16 | 24219022671055626321111109370544217506941658960408 17 | 07198403850962455444362981230987879927244284909188 18 | 84580156166097919133875499200524063689912560717606 19 | 05886116467109405077541002256983155200055935729725 20 | 71636269561882670428252483600823257530420752963450 -------------------------------------------------------------------------------- /euler/09.md: -------------------------------------------------------------------------------- 1 | # 9. Special Pythogorean triple 2 | 3 | https://projecteuler.net/problem=9 4 | 5 | ![Primitive Pythagorean triples, by Adam Cunningham and John Ringland, CC BY-SA 3.0 , via Wikimedia Commons](800px-PrimitivePythagoreanTriplesRev08.svg.png) 6 | 7 | 8 | ## Problem 9 | 10 | A Pythagorean triple is a set of three natural numbers, $a < b < c$, for which 11 | 12 | $$a^2 + b^2 = c^2$$ 13 | 14 | For example, $3^2 + 4^2 = 9 + 16 = 25 = 5^2$. 15 | 16 | There exists exactly one Pythagorean triple for which $a + b + c = 1000$. 17 | Find the product $abc$. 18 | 19 | 20 | ## Solution 21 | 22 | [Euclid’s formula](https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple) allows us to map integer pairs to Pythagorean triples. 23 | 24 | An integer pair $(m,n)$ yields a Pythagorean triple 25 | 26 | $$a = m^2 - n^2, b = 2mn, c = m^2 + n^2$$ 27 | 28 | ```q 29 | sqr:{x*x}til 1000 / cache some squares 30 | dif:.[-] / difference 31 | pt:{(dif sqr x;2*prd x;sum sqr x)} / Pythagorean triple 32 | ``` 33 | 34 | A quick test confirms the upper bound for $m$ and $n$. 35 | 36 | ```q 37 | q)pt 20 19 38 | 39 760 761 39 | 40 | q)cmn:{x where (.[<>]') x} distinct desc each {x cross x} 1+til 20 / candidate m,n pairs 41 | ``` 42 | 43 | It remains only to find the one that sums to 1000. 44 | 45 | ```q 46 | prd{x . (::;) first where 1000=sum x}pt flip cmn 47 | ``` 48 | 49 | ## Notes 50 | 51 | We wrote `pt` to return a triple from an integer pair, but implicit iteration in the primitives means `pt` works just as well on two integer vectors: we don’t nead to `pt each cmn`, just flip `cmn`. 52 | The result is a 3-row matrix of triples, and `1000=sum` flags the column we need. 53 | 54 | Rather than use index brackets with a long expression for the columns 55 | 56 | ```q 57 | x[;blah blah blahdey blah ... ] 58 | ``` 59 | 60 | [Apply](https://code.kx.com/q/ref/apply) accepts a 2-item list in which the first item is the general null `::`. 61 | 62 | ```q 63 | x . (::;) blah blah blahdey blah ... 64 | ``` 65 | 66 | Note the use of a list with a missing element, which here is syntactic sugar for the projection `enlist[::;]`. 67 | 68 | ## Postscript 69 | 70 | I described this problem last weekend to my friend Nick, who teaches maths. 71 | He stared out of the train window for a few minutes before turning back to me and telling me the triple. 72 | 73 | I am hoping to see an update from him here soon. 74 | 75 | [SJT] 76 | 77 | --- 78 | 79 | Contributors 80 | 81 | * Stephen Taylor 82 | -------------------------------------------------------------------------------- /euler/11.q: -------------------------------------------------------------------------------- 1 | /https://projecteuler.net/problem=11 2 | 3 | V:raze M:flip(20#"J";" ")0:`11.txt / ingest and raze 4 | i:shp#til prd shp:count each 1 first\M / indices into V 5 | nc:shp 1 / # cols 6 | 7 | N:4 / # cells to multiply 8 | ri:raze[(N-1)_'i]+\:til N / row indices 9 | ci:raze[(N-1)_i]+\:nc*til N / col indices 10 | tlbr:(raze neg[N]_ neg[N]_'i)+\:(1+nc)*til N / TL-BR diag indices 11 | trbl:(raze neg[N]_ N _'i)+\:(-1+nc)*til N / TR-BL indices 12 | 13 | max prd each V ri,ci,tlbr,trbl 14 | 15 | -------------------------------------------------------------------------------- /euler/11.txt: -------------------------------------------------------------------------------- 1 | 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 2 | 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 3 | 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 4 | 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 5 | 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 6 | 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 7 | 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 8 | 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 9 | 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 10 | 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 11 | 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 12 | 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 13 | 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 14 | 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 15 | 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 16 | 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 17 | 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 18 | 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 19 | 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 20 | 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48 21 | -------------------------------------------------------------------------------- /euler/800px-PrimitivePythagoreanTriplesRev08.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/euler/800px-PrimitivePythagoreanTriplesRev08.svg.png -------------------------------------------------------------------------------- /euler/Sieve_of_Eratosthenes_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/euler/Sieve_of_Eratosthenes_animation.gif -------------------------------------------------------------------------------- /games/fizzbuzz.md: -------------------------------------------------------------------------------- 1 | # Fizz buzz 2 | 3 | 4 | [![Fizz buzz](img/fizzbuzz.png)](https://www.ezrahill.co.uk/2019/04/14/the-fizzbuzz-question/ "Image by Ezra Hill") 5 | 6 | > Fizz buzz is a group word game for children to teach them about division. Players take turns to count incrementally, replacing any number divisible by three with the word _fizz_, and any number divisible by five with the word _buzz_. — [_Wikipedia_](https://en.wikipedia.org/wiki/Fizz_buzz) 7 | 8 | 9 | Fizz buzz is fun for programmers as well as children, and has been implemented in a [host of languages](https://rosettacode.org/wiki/FizzBuzz). 10 | Here is a simple solution in Python for the first hundred numbers. 11 | 12 | ```python 13 | for i in range(1, 101): 14 | if i%3 == 0 and i%5 == 0: 15 | my_list.append("fizzbuzz") 16 | elif i%3 == 0: 17 | my_list.append("fizz") 18 | elif i%5 == 0: 19 | my_list.append("buzz") 20 | else: 21 | my_list.append(i) 22 | ``` 23 | 24 | Since it constructs its results as an array, it could claim to be an array solution. But it employs a for-loop and an if/then/else construct. 25 | We can usually dispense with them in q. 26 | 27 | Start with a vector of numbers. 28 | 29 | ```q 30 | q)show x:1+til 20 31 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 32 | ``` 33 | 34 | We are interested in whether they are divisible by 3 and 5. 35 | Those divisible by 3 have 0 as the result of `x mod 3`. Similarly by 5. Test both. 36 | 37 | ```q 38 | q)0=x mod/:3 5 39 | 00100100100100100100b 40 | 00001000010000100001b 41 | ``` 42 | 43 | But we need four results, not two: divisible by neither; by 3; by 5; and by both. 44 | 45 | ```q 46 | q)1 2*0=x mod/:3 5 47 | 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 48 | 0 0 0 0 2 0 0 0 0 2 0 0 0 0 2 0 0 0 0 2 49 | q)sum 1 2*0=x mod/:3 5 50 | 0 0 1 0 2 1 0 0 1 2 0 1 0 0 3 0 0 1 0 2 51 | ``` 52 | 53 | The items of `x` are mapped to `0 1 2 3`. 54 | 55 | Let’s construct our result as a symbol vector. 56 | 57 | ```q 58 | q)`$string x 59 | `1`2`3`4`5`6`7`8`9`10`11`12`13`14`15`16`17`18`19`20 60 | q)(`$string x;20#`fizz;20#`buzz;20#`fizzbuzz) 61 | 1 2 3 4 5 6 7 8 9 .. 62 | fizz fizz fizz fizz fizz fizz fizz fizz fizz .. 63 | buzz buzz buzz buzz buzz buzz buzz buzz buzz .. 64 | fizzbuzz fizzbuzz fizzbuzz fizzbuzz fizzbuzz fizzbuzz fizzbuzz fizzbuzz fizzb.. 65 | ``` 66 | 67 | We just need a way to use `0 1 2 3` to pick from these four vectors. 68 | Enter the [Case](https://code.kx.com/ref/maps#case) iterator. 69 | 70 | ```q 71 | q)(sum 1 2*0=x mod/:3 5)'[`$string x;20#`fizz;20#`buzz;20#`fizzbuzz] 72 | `1`2`fizz`4`buzz`fizz`7`8`fizz`buzz`11`fizz`13`14`fizzbuzz`16`17`fizz`19`buzz 73 | ``` 74 | 75 | Scalar extension means we can use atoms as the last three arguments. 76 | 77 | ```q 78 | q)(sum 1 2*0=x mod/:3 5)'[`$string x;`fizz;`buzz;`fizzbuzz] 79 | `1`2`fizz`4`buzz`fizz`7`8`fizz`buzz`11`fizz`13`14`fizzbuzz`16`17`fizz`19`buzz 80 | ``` 81 | 82 | This is a good example of ‘array thinking’. 83 | 84 | > — What is the problem? I can write for-loops in my sleep. 85 | >
86 | > — _We want you to wake up._ 87 | 88 | Notice how much of the expression simply states the problem. 89 | 90 | ``[`$string x;`fizz;`buzz;`fizzbuzz]`` lists the four possible result options. 91 | 92 | `0=x mod/:3 5` tests for divisibility by 3 and 5. 93 | 94 | `(sum 1 2* .. )'[ .. ]` relates the test results to the final results. This is the only ‘programmery’ bit. The other two parts correspond directly to the posed problem. 95 | 96 | In this way the solution exhibits high _semantic density_: most terms in the code correspond to terms in the problem domain. 97 | 98 | --- 99 | 100 | On semantic density: 101 | 102 | * [“Three Principles of Code Clarity”](http://archive.vector.org.uk/art10009750 "Vector, the journal of the British APL Association"), _Vector_ 18:4 103 | * [“Pair programming With The Users](http://archive.vector.org.uk/art10009900 "Vector, the journal of the British APL Association"), _Vector_ 22:1 104 | 105 | -------------------------------------------------------------------------------- /games/img/boggle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/games/img/boggle.jpg -------------------------------------------------------------------------------- /games/img/fizzbuzz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/games/img/fizzbuzz.png -------------------------------------------------------------------------------- /games/img/klondike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/games/img/klondike.png -------------------------------------------------------------------------------- /games/img/scrabble.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/games/img/scrabble.jpg -------------------------------------------------------------------------------- /games/klondike.q: -------------------------------------------------------------------------------- 1 | / klondike 2 | / https://en.wikipedia.org/wiki/Klondike_(solitaire) 3 | / Usage: see g:deal[] 4 | / see g:move[g] `9C`TH 5 | / see g:move[g] `AS 6 | / see g:move[g] `KC 7 | / see g:turn g 8 | 9 | SUITS:"SHCD" 10 | NUMBERS:"A23456789TJQK" 11 | SYM:`$NUMBERS cross SUITS / card symbols 12 | SYM,:`$("[]";"__") / hidden card; empty stack; blank space 13 | HC:52 / hidden card 14 | ES:53 / empty stack 15 | SP:54 / blank space 16 | 17 | NUMBER:1+til[13]where 13#4 / card numbers 18 | SUIT:52#SUITS / card suits 19 | COLOR:"RB" SUIT in "SC" / card colors 20 | TURN:3 / # cards to turn 21 | 22 | STOCK:0 23 | WASTE:1 24 | FOUNDATION:2+til 4 25 | TABLEAU:6+til 7 26 | 27 | ce:count each 28 | le:last each 29 | tc:til count :: 30 | 31 | deal:{[] 32 | g:()!(); 33 | deck:-52?52; 34 | / columns: stock, waste, 4 foundations, 7 piles 35 | g[`c]:13#enlist 0#0; 36 | g[`c;TABLEAU]:(sums til 7)_ 28#deck; / tableau 37 | g[`x]:le g[`c;TABLEAU]; / exposed 38 | g[`c;STOCK]:28_ deck; 39 | g[`s]:0; / score 40 | g[`p]:0; / # passes 41 | turn g } 42 | 43 | move:{[g;y] / move y (symbol atom or pair) 44 | if[not 99h~type g; '"not a game"]; 45 | if[not all `c`p`x`pm in key g; '"not a game"]; 46 | if[abs[type y]<>11; '"type"]; 47 | if[(type[y]>0)and 2<>count y; '"length"]; 48 | if[not all b:y in SYM; '"invalid card: "," "sv string y where not b]; 49 | 50 | cards:SYM?y; 51 | / map cards to n,f,t 52 | cl:ce g`c; / column lengths 53 | f:first where cl>i:g[`c]?'first cards; / from column 54 | n:cl[f]-i[f]; / # cards to move 55 | t:$[2=count cards; first where cl>g[`c]?'cards 1; 56 | $[1=NUMBER first cards; first[FOUNDATION]+SUITS?SUIT first cards; 57 | first[TABLEAU]+first where 0=ce g[`c;TABLEAU] ] 58 | ]; 59 | if[not(n,f,t)in g`pm; '"invalid move"]; 60 | move_[g;n;f;t] } 61 | 62 | move_:{[g;n;f;t] 63 | / move n cards in g from g[`c;f] to g[`c;t] 64 | g[`c;t],:neg[n]#g[`c;f]; 65 | g[`c;f]:neg[n]_ g[`c;f]; 66 | let:le g[`c;TABLEAU]; 67 | g[`s]+:5 0@all let in g`x; / turned over tableau card? 68 | g[`x]:distinct g[`x],let; 69 | g[`s]+:$[f=WASTE; 5 10@t in FOUNDATION; 70 | f in TABLEAU; 0 10@t in FOUNDATION; 71 | f in FOUNDATION; -15; 72 | 0 ]; / score 73 | rpm g } 74 | 75 | rpm:{[g] / record possible moves 76 | top:{(y,'i-1)where 0;COLOR(cards;tgts)]and 1=.[-]NUMBER(tgts;cards)) 89 | or (tgts=0N)and NUMBER[cards]=13 90 | }[g`c] (top[WASTE,FOUNDATION],xit) cross TABLEAU; 91 | / # cards to move 92 | g[`pm]:{(ce[x y[;0]]-y[;1]),'y[;0 2]}[g`c] fm,tm; 93 | g } 94 | 95 | see:{[g] / display game 96 | / stock, waste, foundations 97 | top:{((HC;ES)count[x]=0),ES^y}. 0 1 _ le g[`c;STOCK,WASTE,FOUNDATION]; 98 | show (`$string count[g[`c;STOCK]],g`p),'SYM 2 7#(2#top),SP,(2_ top),7#SP; 99 | / columns 100 | show SYM {flip x[;til max ce x]}{x,'(0=ce x)#'ES}{[g;c]g[`c;c]|HC*not g[`c;c]in g[`x]}[g] TABLEAU; 101 | show 21#"_"; 102 | show "score: ",string g`s; 103 | show $[0=count g`pm; "No moves possible"; 104 | {[g;n;f;t] SYM first each neg[n,1]#'g[`c;f,t]}[g;].'g`pm ]; } 105 | 106 | turn:{[g;n] 107 | trn:0=count g[`c;STOCK]; 108 | g[`c;STOCK,WASTE]:g[`c;trn rotate STOCK,WASTE]; 109 | g[`p]+:trn; / # passes 110 | move_[g; n&count g[`c;STOCK]; STOCK; WASTE] }[;TURN] 111 | 112 | -------------------------------------------------------------------------------- /games/scrabble.md: -------------------------------------------------------------------------------- 1 | # Cheat at Scrabble 2 | 3 | 4 | [![Scrabble](img/scrabble.jpg)](https://scrabble.hasbro.com/en-us "Official Scrabble site") 5 | 6 | 7 | **Problem** Given a string representing the letters in a [Scrabble™](https://scrabble.hasbro.com/en-us) player’s rack, produce candidate words for the next turn, ranked by potential score. (The score ignores the effect of placement on the board, such as Double Letter Score, etc.) 8 | 9 | [Rules of Scrabble](https://en.wikipedia.org/wiki/Scrabble "Wikipedia") 10 | 11 | ## Techniques 12 | 13 | - Download a word list from the Web 14 | - Make a q dictionary 15 | - Count frequencies of items in a list 16 | - Subtract one dictionary from another 17 | - Use function notation within a [qSQL](https://code.kx.com/q/basics/qsql) query 18 | 19 | 20 | ## Solution 21 | 22 | ```q 23 | / Scrabble tile values 24 | TV:.Q.a!1 3 3 2 1 4 2 4 1 8 5 1 3 1 1 3 10 1 1 1 1 4 4 8 4 10 25 | 26 | / Unix dictionary 27 | UD:system "curl http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" 28 | 29 | / frequency count 30 | fc:{count each group x} 31 | 32 | / dictionary table 33 | DT:([] word:UD; fr:fc each UD; sc:{sum TV x}each UD) 34 | 35 | / word builder 36 | wb:{{x idesc x`sc}select word,sc from DT where fc[x]{all(x-y)>=0}/:fr} 37 | ``` 38 | 39 | 40 | ## Usage 41 | 42 | ```q 43 | q)wb "eobmagl" 44 | word sc 45 | ----------- 46 | "gamble" 11 47 | "gambol" 11 48 | "amble" 9 49 | "blame" 9 50 | "mabel" 9 51 | "bagel" 8 52 | "balm" 8 53 | .. 54 | ``` 55 | 56 | [Official Scrabble site word builder](https://scrabble.hasbro.com/en-us/tools#wordbuilder) 57 | 58 | 59 | ## Discussion 60 | 61 | ```q 62 | q)sum TV "scrabble" / score a word 63 | 14 64 | ``` 65 | 66 | For each word, make a frequency count of its letters as a dictionary. 67 | 68 | ```q 69 | q)fc "scrabble" 70 | s| 1 71 | c| 1 72 | r| 1 73 | a| 1 74 | b| 2 75 | l| 1 76 | e| 1 77 | ``` 78 | 79 | Tabulate the words, their frequency counts, and the word scores. 80 | 81 | ```q 82 | q)DT 83 | word fr sc 84 | ----------------------------- 85 | ,"a" (,"a")!,1 1 86 | "aaa" (,"a")!,3 3 87 | "aaas" "as"!3 1 4 88 | "aarhus" "arhus"!2 1 1 1 1 9 89 | "aaron" "aron"!2 1 1 1 5 90 | "aau" "au"!2 1 3 91 | "aba" "ab"!2 1 5 92 | .. 93 | ``` 94 | 95 | To test a word, subtract its frequency count from the frequency count of the tiles on your rack. 96 | 97 | ```q 98 | q)fc["eobmagl"]-fc "mangle" 99 | e| 0 100 | o| 1 101 | b| 1 102 | m| 0 103 | a| 0 104 | g| 0 105 | l| 0 106 | n| -1 107 | q)all 0<=fc["eobmagl"]-fc "mangle" / is "mangle" possible? 108 | 0b 109 | ``` 110 | 111 | If no item is negative, the word is a candidate. 112 | 113 | 114 | The expression `fc[x]{all(x-y)>=0}/:fr` applies the test to flag words that can be formed from the letters in the tray `x`. 115 | It takes the frequency count of the tray letters `fc[x]` and uses [Each Right](https://code.kx.com/q/ref/maps#each-left-and-each-right) to apply the test to the frequency counts in the `fr` column. 116 | 117 | It remains only to sort the candidates descending by score. -------------------------------------------------------------------------------- /leetcode/53.q: -------------------------------------------------------------------------------- 1 | // maximum contiguous subarray 2 | // https://leetcode.com/problems/maximum-subarray/ 3 | 4 | / exemplary problems 5 | / https://martin-thoma.com/maximum-subarray-sum/ 6 | E0: 11 -5 -5 -2 1 2 3 4 5 0 1 / 16 7 | E1: 9 -5 -5 -2 1 2 -1 4 5 0 1 / 12 8 | E2: -1 -2 -3 -4 -5 / -1 9 | E3: 1#-2 / -2 10 | E4: 1#3 / 3 11 | 12 | M9: -10+9000000?20 13 | 14 | / brute force: generate and sum all subarrays 15 | mcs0:{max sum each raze x tcx+neg[tcx]_\:til each 1+tcx:til count x} 16 | 17 | / simple adaptation of Kadane's algorithm 18 | mcs1: max ((0|+)\) @ 19 | 20 | / also track current max and actual max 21 | mcs2:{{(y;z)z<0}.(0,2#x 0) {(0|y+x 0;x[1]|0|y+x 0; y|x 2)}/x} 22 | 23 | / https://stackoverflow.com/questions/74508773 24 | mcs3:{max s-mins 0^prev s:sums x} 25 | / mcs4:{max s-mins 0f,1_prev s:sums x} 26 | / mcs5:{max s-mins 0,1_prev s:sums x} 27 | 28 | examples:(E0;E1;E2;E3;E4) 29 | 30 | show (mcs0;mcs1;mcs2;mcs3)@/:\:examples 31 | / show (mcs0;mcs1;mcs2;mcs3;mcs4;mcs5)@/:\:examples 32 | 33 | show (mcs1;mcs2;mcs3)@\:M9 34 | / show (mcs1;mcs2;mcs3;mcs4;mcs5)@\:M9 35 | 36 | show{flip`f`t`s!flip x,'(system raze("ts ";;" M9")@)each string x}`mcs1`mcs2`mcs3 37 | -------------------------------------------------------------------------------- /leetcode/976.md: -------------------------------------------------------------------------------- 1 | # 976. Largest Perimeter Triangle 2 | 3 | https://leetcode.com/problems/largest-perimeter-triangle/ 4 | 5 | > Given an integer array `nums`, return the largest perimeter of a triangle with a non-zero area, formed from three of these lengths. If it is impossible to form any triangle of a non-zero area, return 0. 6 | 7 | 8 | ## Solutions 9 | 10 | The length of the perimeter of a triangle is the sum of the lengths of its sides. 11 | 12 | The longest perimeter will be the sum of the three largest items – 13 | provided that they can form a triangle. 14 | 15 | They cannot form a triangle if the largest length exceeds the sum of the smaller two. 16 | If it does, it cannot form a triangle with any of the remaining lengths either, because they are shorter still. 17 | It can therefore be discarded. 18 | 19 | We have the start of a plan. 20 | Sort the lengths descending. Try the first three. 21 | 22 | 23 | ### Recursion 24 | 25 | ```q 26 | q)ex1:2 1 2 / triangle 27 | q)ex2:1 2 1 / not 28 | q)show ex3:10?10 / ??? 29 | 8 1 9 5 4 6 6 1 8 5 30 | q)desc ex3 31 | 9 8 8 6 6 5 5 4 1 1 32 | q){x[0]=sum x i 1 2; i+:1]; 56 | sum x i } desc@ 57 | ``` 58 | 59 | The same algorithm can be expressed with the While iterator. 60 | Start with the sorted list and three indices. 61 | Use [Amend At](https://code.kx.com/q/ref/amend) to increment the indices. 62 | 63 | ```q 64 | q)(desc ex3;til 3) 65 | 9 8 8 6 6 5 5 4 1 1 66 | 0 1 2 67 | 68 | q)@[;1;1+](desc ex3;til 3) 69 | 9 8 8 6 6 5 5 4 1 1 70 | 1 2 3 71 | ``` 72 | 73 | Now apply the [While form of Over](https://code.kx.com/q/ref/accumulators/#while) with a test that returns zero 74 | if the three lengths make a triangle. 75 | 76 | ```q 77 | q){{x[0]>=sum x 1 2}x y}. @[;1;1+](desc ex3;til 3) 78 | 0b 79 | q)sum .[@]({{x[0]>=sum x 1 2}x y}.) @[;1;1+]/(desc ex3;til 3) 80 | 25 81 | q)s2:sum .[@] {({{x[0]>=sum x 1 2}x y}.) @[;1;1+]/x} (;til 3) desc@ 82 | q)s2 each(ex1;ex2;ex3) 83 | 5 0 25 84 | ``` 85 | 86 | The `(;til 3)desc@` yields the sorted list and the first three indexes; the While expression increments the indexes; the `.[@]` selects the indexed list items and `sum`, well, sums them. 87 | 88 | 89 | ## Alternatives 90 | 91 | ```q 92 | / Cillian Reilly 93 | c0:{sum w first where{x=sum x i 1 2; i+:1]; 113 | sum x i } desc@ / while 1 114 | 115 | s2:sum .[@] {({{x[0]>=sum x 1 2}x y}.) @[;1;1+]/x} (;til 3) desc@ / while 2 116 | ``` 117 | 118 | ## Performance 119 | 120 | Validate: 121 | 122 | ```q 123 | q)ex4:10000?1000000 / per LeetCode constraints 124 | 125 | q)(c0;c1;g2;s0;s1;s2)@/:\:(ex1;ex2;ex3;ex4) 126 | 5 0 25 2999307 127 | 5 0 25 2999307 128 | 5 0 25 2999307 129 | 5 0 25 2999307 130 | 5 0 25 2999307 131 | 5 0 25 2999307 132 | ``` 133 | 134 | ```q 135 | q){x,system"ts:100 ",string[x]," ex4"}each `c0`c1`g2`s0`s1`s2 136 | `c0 693 1557568 137 | `c1 17 655616 138 | `g2 18 655728 139 | `s0 16 655584 140 | `s1 16 655584 141 | `s2 16 655584 142 | ``` 143 | 144 | --- 145 | 146 | Contributors 147 | 148 | * Cillian Reilly 149 | * George Berkeley 150 | * Stephen Taylor -------------------------------------------------------------------------------- /leetcode/976.q: -------------------------------------------------------------------------------- 1 | / https://leetcode.com/problems/largest-perimeter-triangle/ 2 | 3 | / Given an integer array `nums`, return the largest perimeter of a triangle with a non-zero area, 4 | / formed from three of these lengths. 5 | / If it is impossible to form any triangle of a non-zero area, return 0. 6 | 7 | ex1:2 1 2 / LeetCode example 1: triangle 8 | ex2:1 2 1 / LeetCode example 2: not 9 | ex3:8 1 9 5 4 6 6 1 8 5 / short test 10 | ex4:10000?1000000 / per LeetCode constraints 11 | 12 | / Cillian Reilly 13 | c0:{sum w first where{x=sum x i 1 2; i+:1]; 27 | sum x i } desc@ / while 1 28 | 29 | s2:sum .[@] {({{x[0]>=sum x 1 2}x y}.) @[;1;1+]/x} (;til 3) desc@ / while 2 30 | -------------------------------------------------------------------------------- /puzzles/100prisoners.md: -------------------------------------------------------------------------------- 1 | # One Hundred Prisoners 2 | 3 | The [One Hundred Prisoners problem](https://en.wikipedia.org/wiki/100_prisoners_problem "Wikipedia") has a famously counter-intuitive solution, nicely explained on YouTube: 4 | 5 | https://www.youtube.com/watch?v=iSNsgj1OCLA 6 | 7 | Exploring it in q is illuminating! 8 | 9 | George Berkeley kicked this off in the Vector Dōjō : 10 | 11 | > A problem I found interesting, and maybe you will too… You can view a vector `v = (1 0 2 3 5 6 4)` as a permutation, i.e. given an index `i`, the permutation sends `i` to `v[i]`. If we apply the permutation multiple times, then eventually we end up where we started. In fact, if we look at `v`, we can see it breaks down into the following cycles: 12 | > 13 | > 0 -> 1 -> 0 14 | > 2 -> 2 15 | > 3 -> 3 16 | > 4 -> 5 -> 6 -> 4 17 | > 18 | > Given a permutation, return the number of cycles! (so 4 for the given `v`) 19 | 20 | ```q 21 | q)v:1 0 2 3 5 6 4 22 | q)v scan 0 23 | 0 1 24 | q)(v scan)each 0 2 3 4 25 | 0 1 26 | ,2 27 | ,3 28 | 4 5 6 29 | ``` 30 | 31 | Each item belongs to one and only one cycle. Above, we see all the items, so we see there are only four cycles. A more brute-force approach: 32 | 33 | ```q 34 | q)(v scan)each v 35 | 1 0 36 | 0 1 37 | ,2 38 | ,3 39 | 5 6 4 40 | 6 4 5 41 | 4 5 6 42 | ``` 43 | 44 | `0 1` and `1 0` are the same cycle. Sorting each cycle lets us remove duplicates and count. 45 | 46 | ```q 47 | q)distinct(asc v scan)each v 48 | `s#0 1 49 | `s#,2 50 | `s#,3 51 | `s#4 5 6 52 | 53 | q)count distinct(asc v scan)each v 54 | 4 55 | ``` 56 | 57 | Rian Ó Cuinnegáin linked the problem to the One Hundred Prisoners problem. The key to the problem (spoiler) is that in 100-item permutations, there is about a one-in-three chance that the maximum cycle length is no more than 50. (Above, it is 3.) 58 | 59 | ```q 60 | q)max(count v scan)each v 61 | 3 62 | q)max{(count x scan)each x} -100?100 63 | 44 64 | q)max{(count x scan)each x} -100?100 65 | 55 66 | q)max{(count x scan)each x} -100?100 67 | 90 68 | ``` 69 | 70 | This could be smarter. Consider the last case. The longest cycle has 90 items. Once it is found, we have the cycle length for all 90 of its items. We no longer need to evaluate the other 89. 71 | 72 | Let’s work on a state with three items: the cycle length for each index, the permutation itself, and the untested indices. 73 | 74 | ```q 75 | q)show q:-10?10 / test 76 | 5 0 1 9 2 6 8 4 7 3 77 | q)is:(#[;0]count@;::;til count@)@\: / initial state 78 | q)is q 79 | 0 0 0 0 0 0 0 0 0 0 80 | 5 0 1 9 2 6 8 4 7 3 81 | 0 1 2 3 4 5 6 7 8 9 82 | ``` 83 | 84 | Now a step function that updates the state by evaluating the next index. 85 | 86 | ```q 87 | q)step:{[c;p;i] if[count i;c[r]:count r:p scan i 0];(c;p;where not c)} . 88 | 89 | q)step is q 90 | 8 8 8 0 8 8 8 8 8 0 91 | 5 0 1 9 2 6 8 4 7 3 92 | 3 9 93 | ``` 94 | 95 | Above, the cycle of which 0 is a member has length 8. After the first step, only two indices remain to evaluate. 96 | So much less work to do: 97 | 98 | ```q 99 | q)p:-100?100 100 | 101 | q)\t:1000 max(count p scan)each p 102 | 134 103 | q)\t:1000 max first step over is p 104 | 13 105 | ``` 106 | 107 | This approach also quickly gives us the answer to the question George first posed: how many cycles are in the permutation? The first item of a scan result is of course the initial state; we count the rest. 108 | 109 | ```q 110 | q)-1+ count step scan is v 111 | 4 112 | q)-1+ count step scan is p 113 | 6 114 | ``` 115 | 116 | My thanks to Vector Dōjō tutors Rian Ó Cuinnegáin and Cillian Reilly for their work on this. 117 | -------------------------------------------------------------------------------- /puzzles/img/cats-cradle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qbists/studyq/efe1da1a9c31044580c573f59e9f669d5a646e67/puzzles/img/cats-cradle.jpg -------------------------------------------------------------------------------- /puzzles/run-length-encoding.md: -------------------------------------------------------------------------------- 1 | # Run-length encoding 2 | 3 | ## Problem 4 | 5 | Suppose we have a string of characters from the English alphabet: 6 | 7 | ```q 8 | "aaaaaaaabbbbbbcccdeeeeeeefffbbaaab" 9 | ``` 10 | 11 | All of that repetition hurts the eyes! Please fix it by implementing the rule: 12 | 13 | * groups of repeating characters are replaced by the character followed by its count; 14 | * groups of one character are left alone. 15 | 16 | Applying this rule, the above becomes a slender: 17 | 18 | ```q 19 | "a8b6c3de7f3b2a3b" 20 | ``` 21 | 22 | Much nicer! 23 | 24 | ## Solution 1 25 | 26 | Let's tackle the problem in 2 steps. First, we split the string into character groups. Second, we calculate the counts and construct the output string. 27 | 28 | To find the character groups, it is enough to locate where a character differs from its predecessor. This is a pretty common task, and luckily for us Q handles it out of the box: 29 | 30 | ```q 31 | q)s:"aaaaaaaabbbbbbcccdeeeeeeefffbbaaab" 32 | q)differ s 33 | 1000000010000010011000000100101001b 34 | ``` 35 | 36 | With mask in hand, cutting the string is straightforward: 37 | 38 | ```q 39 | q)(where differ s) cut s 40 | "aaaaaaaa" 41 | "bbbbbb" 42 | "ccc" 43 | ,"d" 44 | "eeeeeee" 45 | "fff" 46 | "bb" 47 | "aaa" 48 | ,"b" 49 | ``` 50 | 51 | From here we compute the counts and apply our rule, being careful to handle the single character special case! 52 | 53 | ```q 54 | q){(x;(first x),string cnt) 1