Tim (2021)
My solutions will all be in DataQube which is not actually a language, but a computational system and application builder for performing manipulations and computations on data.
I will go as far as I can with DataQube, but some problems may be out of reach of DQ's (or my) capability.
My posts are in a tabular format in two parts - the solution followed by a narrative.
The solution part consists of one or more tables displaying a series of objects. The first object (left most column) contains the problem data. The objects (columns) that follow show the results of successive steps in the computation.
The narrative part shows the type and definition of each object in the series, along with additional information to clarify what each object does. Objects shown in blue are "Open" (not computed) and objects shown in red are "Dependent" (computed).
Day 1 Solutions: (Sonar Sweep)
# | Selected Data (Depth) | Sub1 | Sub2 | Comparison Mask | Increase Cnt | Sliding Window Sums | Sliding Window Increase Cnt |
---|---|---|---|---|---|---|---|
1 | 199 | 199 | 200 | 1 | 7 | 607 | 5 |
2 | 200 | 200 | 208 | 1 | 618 | ||
3 | 208 | 208 | 210 | 1 | 618 | ||
4 | 210 | 210 | 200 | 0 | 617 | ||
5 | 200 | 200 | 207 | 1 | 647 | ||
6 | 207 | 207 | 240 | 1 | 716 | ||
7 | 240 | 240 | 269 | 1 | 769 | ||
8 | 269 | 269 | 260 | 0 | 792 | ||
9 | 260 | 260 | 263 | 1 | |||
10 | 263 |
Day 1 Narrative:
Object | Evaluates To | Explanation |
---|---|---|
Selected Data | Integer Array | The depth data selected for the current computaion. This is a dependent object, but its definition is not important to the solution. |
Sub1 | Integer Array | = "Selected Data" [1.. -2] The subset of "Selected Data" containing the first through the second to last values. |
Sub2 | Integer Array | = "Selected Data" [2.. -1] The subset of "Selected Data" containing the second through the last values. |
Comparison Mask | Mask | = "Sub2" > "Sub1" A Mask indicating where "Sub2" > "Sub1". |
Increase Cnt | Scalar | = GSum( "Comparison Mask" ) THE RESULT FOR PART A. (The number of times the depth increases from one measurement to the next.) The GSum( ... ) function takes the global sum of the values in its argument. |
Sliding Window Sums | Real Array | = Pack(RSum( "Selected Data" by 3) ) The sliding window sums for part B. RSum("Selected Data" by 3) computes the 3-value running sums of the data. (The successive sums of a 3-value sliding window.) This results in an array the same length as "Selected Data" with no values in the first two cells. Pack( ... ) removes the empty cells, resulting in an array two shorter than the original data array. |
Sliding Window Increase Cnt | Scalar | = GSum( "Sliding Window Sums" [2.. -1] > "Sliding Window Sums" [1.. -2]) THE RESULT FOR PART B. This computaion is identical to that for "Increase Cnt" except that it is performed on the sliding window sums instead of the orginal data. |
Day 2 Solutions: (Dive)
# | Selected Data | Dir | Dist | F | D | U | Final Pos A | Final Depth A | Product A | Current Aim B | Currrent Depth B | Final Depth B | Product B |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | forward 5 | f | 5 | 5 | 15 | 10 | 150 | 0 | 0 | 60 | 900 | ||
2 | down 5 | d | 5 | 5 | 5 | 0 | |||||||
3 | forward 8 | f | 8 | 8 | 5 | 40 | |||||||
4 | up 3 | u | 3 | 3 | 2 | 40 | |||||||
5 | down 8 | d | 8 | 8 | 10 | 40 | |||||||
6 | forward 2 | f | 2 | 2 | 10 | 60 |
Day 2 Narrative:
Object | Evaluates To | Explanation |
---|---|---|
Selected Data | List | The direction/distqance data selected for the current computaion. This is a dependent object, but its definition is not important to the solution. |
Dir | List | = "Selected Data" {1} Direction indicators extracted from "Selected Data". The {...} construct extracts subsets of characters from strings. |
Dist | Real Array | = Extract#( "Selected Data" ) Distance values extracted from "Selected Data". |
F | Real Array | = "Dist" `[ "Dir" = 'F'] The distances for the forward direction. When the [...] construct is preceded by the ` unuary operator, the extracted values retain their original positions. |
D | Real Array | = "Dist" `[ "Dir" = 'D'] The distances for the down direction. |
U | Real Array | = "Dist" `[ "Dir" = 'U'] The distances for the up direction. |
Final Pos A | Scalar | = GSum( "F" ) The final position for part A. |
Final Depth A | Scalar | = GSum( "D" ) - GSum( "U" ) The final depth for part A. (The sum of the down distances - the sum of the up distances.) |
Product A | Scalar | = "Final Pos A" * "Final Depth A" THE RESULT FOR PART A. |
Current Aim B | Real Array | = CSum( "D" & Neg( "U" ) ) & 0 The cumulative Aim. The & operrator fills empty spaces in the first argument with corresponding values in the second argument where present. CSum(...) computes the cumulative sum of the values in its argument. |
Current Depth B | Real Array | = CSum( "Current Aim B" * "F" ) The cumualtive depth. |
Final Depth B | Scalar | = "Currrent Depth B" [ -1] The final depth. |
Product B | Scalar | = "Final Pos A" * "Final Depth B" THE RESULT FOR PART B. |
Day 3A Solution: (Binary Diagnostics)
(Table shows only the first 15 of 60 lines of data.)
# | Selected Data | Data Matrix | Data Matrix Groups | Bit Positions | Freq of Ones | HalfSz | Gamma Binary Array | Epsilon Binary Array | Gamma | Epsilon | Gamma Decimal | Epsilon Decimal | Product |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 00100 | 0 | 0 | 1 | 7 | 6 | 1 | 0 | 10110 | 01001 | 22 | 9 | 198 |
2 | 11110 | 0 | 0 | 2 | 5 | 0 | 1 | ||||||
3 | 10110 | 1 | 0 | 3 | 8 | 1 | 0 | ||||||
4 | 10111 | 0 | 0 | 4 | 7 | 1 | 0 | ||||||
5 | 10101 | 0 | 0 | 5 | 5 | 0 | 1 | ||||||
6 | 01111 | 1 | 1 | 1 | |||||||||
7 | 00111 | 1 | 1 | 2 | |||||||||
8 | 11100 | 1 | 1 | 3 | |||||||||
9 | 10000 | 1 | 1 | 4 | |||||||||
10 | 11001 | 0 | 1 | 5 | |||||||||
11 | 00010 | 1 | 0 | 1 | |||||||||
12 | 01010 | 0 | 0 | 2 | |||||||||
13 | 1 | 0 | 3 | ||||||||||
14 | 1 | 0 | 4 | ||||||||||
15 | 0 | 0 | 5 |
Day 3A Narrative:
Object | Evaluates To | Explanation |
---|---|---|
Selected Data | List | The binary code data selected for the current computaion. This is a dependent object, but its definition is not important to the solution. |
Data Matrix | Real Array | = Num(Parse( "Selected Data" by '') ) The list of binary codes parsed into a continuous array. The Parse(...) function parses strings into substrings by the specified delimiter. In this case, an empty string is passed as the delimiter, so each of the code strings is parsed into its individual characters (0s and 1s), The resulting list is then converted to a numeric array with Num(...). |
Data Matrix Groups | Mask | = AltMsk(ParseSzs( "Selected Data" by '') ) An alternating mask indicating the bit groups in the data matrix. The ParseSzs(...) function returns an array of group sizes (the number of substrings that each of the strings in the input list is parsed into). This array of group sizes is then used to generate an alternating mask with the AltMsk(...) function. |
Bit Positions | Integer Array | = GrpDatTly( "Data Matrix Groups" ) The bit positions corresponding to the bit values in "Data Matrix". The GrpDatTly(...) function (GroupDataTally) indexes the values in each group of like values in the argument. |
Freq of Ones | Real Array | = SumOf( "Data Matrix" by "Bit Positions" ) Frequency of ones in each bit position in the data matrix. |
HalfSz | Scalar | = SzOf("Selected Data")/2 Half the size of "Selected Data". |
Gamma Binary Array | Mask | = "Freq of Ones" >= "HalfSz" Mask indicating bit positions where the frequency of ones >= half the size of the dataset. |
Epsilon Binary Array | Mask | = "Freq of Ones" <= "HalfSz" Mask indicating bit positions where the frequency of ones <= half the size of the dataset. Note that this is not necessarily the 'logical not' of "Gamma Binary Array". If the ones and zeros are evenly split, the >=/<= comparisons will yield true for both Gamma and Epsilon. |
Gamma | String | = GSum(Txt( "Gamma Binary Array" ) ) Most common bit in each position. The Txt(...) function returns the text representation of its numeric argument. The GSum(...) funtions operates on lists by catenating all the strings in the list into a single string. |
Epsilon | String | = GSum(Txt( "Epsilon Binary Array" ) ) Least common bit in eavh position. |
Gamma Decimal | Scalar | = GSum( (2^Rev(Ndx(SzOf( "Gamma Binary Array" ) ) - 1) ) * "Gamma Binary Array" ) Gamma converted to decimal value. DataQube has no functions for working with binary numbers so this is done by brute force. An index the size of "GammaBinary Array" is generated, its order is reversed and one is subtracted resulting in the array [4,3,2,1,0] (not shown). These are used as the exponents for 2, resulting in the array [2^4 , 2^3 , 2^2 , 2^1 , 2^0] (also not shown). This array is then multiplied by "Gamma Binary Array" so that the only non-zero elements that remain correspond to the 1 bits. The result is then summed to get the decimal equivalent. |
Epsilon Decimal | Scalar | = GSum( (2^Rev(Ndx(SzOf( "Epsilon Binary Array" ) ) - 1) ) * "Epsilon Binary Array" ) Epsilon converted to decimal value. |
Product | Scalar | = "Gamma Decimal" * "Epsilon Decimal" THE RESULT FOR PART A. |
Day 3B (O2 Gen) Solution:
In DataQube, the user does not write "code" (statements, functions, procedures). Instead, series of objects are created that define computational trains. Whenever the data changes in one or more objects, all the descendants of those objects are marked as invalid so they are evaluated in the next global computation. Since there are no user defined procedures or functions, recursion cannot be implemented. DQ does have some functions that can be used to push results back to an earlier stage in the computational train, and it has one function that allows the user to explicitly implement loops at a macroscopic level. The following solution combines "push" functions with the "Animate" function to implement a computational loop with feedback.
Table shows the state of the objects at the end of the computation.
# | Selected Data | Num Bits | Bit Positions | Bit Pos | Data0 | Half Sz | Current Bit | MCB | Retain | Z | Backfeed | Result Binary Array | Decimal Result |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 00100 | 5 | 1 | 5 | 10110 | 1 | 0 | 1 | 10111 | 1 | 0 | 1 | 23 |
2 | 11110 | 2 | 10111 | 1 | 0 | ||||||||
3 | 10110 | 3 | 1 | ||||||||||
4 | 10111 | 4 | 1 | ||||||||||
5 | 10101 | 5 | 1 | ||||||||||
6 | 01111 | ||||||||||||
7 | 00111 | ||||||||||||
8 | 11100 | ||||||||||||
9 | 10000 | ||||||||||||
10 | 11001 | ||||||||||||
11 | 00010 | ||||||||||||
12 | 01010 |
The following video shows the full computation slowed down so you can see the results of each step.
Day 3B O2 Gen Narrative:
Object | Type | Explanation |
---|---|---|
Selected Data | List | The binary code data selected for the current computaion. This is a dependent object, but its definition is not important to the solution. |
Num Bits | Scalar | = TxtLen( "mSelected Data" [1]) The number of bits in the data values. |
Bit Positions | Index | = Ndx( "nNumBits" ) Array of bit positions over which to iterate. |
Bit Pos | Scalar | Bit position for the current iteration in the computational loop. Set to zero on initialization, set to one to start computation. |
Data0 | List | Data for the current iteration. Set to "Selected Data" on initialization. At the start of each iteration, set to data retained from previous iteration. |
Half Sz | Scalar | = If( "Bit Pos" , DatSz( "Data0" ) /2 Else 0) Half size of "Data0". Only computes if "Bit Pos" is non-zero (computaional loop is executing) else set to 0. The if construct interprets its first argument as boolean. Zero is false, non-zero is true. |
Current Bit | Real Array | = If( "Bit Pos" , Num( "Data0" { "Bit Pos" }) Else Array(2) ) Bits in current position. Only computes if "Bit Pos" in non-zero else set to an empty array. |
MCB | Scalar | If( "Bit Pos" , (GSum( "Current Bit" ) >= "Half Sz" ) Else 0) Most common bit in current position. Only computes if "Bit Pos" is non-zero elsee set to 0. |
Retain | List | = If( ( "Bit Pos" ) , ( "Data0" [ "Current Bit" = "MCB" ]) Else List(2) ) Retains only the data values that have the most common bit in the current position.. At end of iterations, this is the result. Only computes if "Bit Pos" is non-zero else set to an empty list. |
Z | Scalar | = If( "Bit Pos" , (DatSz( "Retain" ) <= 1) Else 0) Stop indicator: Goes to one when there is only one value left in "Retain", causing iterations to stop. Only computes if "Bit Pos" is non-zero, else set to 0. |
Backfeed | Scalar | = If( ( ( "Bit Pos" > 1) and Not( "Z" ) ) , SetDat( "Data0" to "Retain" ) ) Feeds the data to be retained back into 'Data0' as after Although the ancestry of this object includes "Z" and "Data0", it is configured to evaluate only when "Bit Pos" changes at the beginning of the iteration. If this were not the case, it would execute when "Z", "Data0", and "Retain" were initialized and also form a loop with "Data0", causing spurious evaluations. |
Result Binary Array | Real Array | = If( "Z" , Num(Parse( "Retain" by '') ) Else 0) Binary array of final result. Evaluates only once Z goes positive. Parses the single string remaining in "Retain" into a list and then converts the list to an array. |
Decimal Result | Scalar | = GSum( (2^Rev(Ndx(SzOf( "Result Binary Array" ) ) - 1) ) * "Result Binary Array" ) O2 Gen Result |
Init | Scalar | Not shown in solution table. (Has Formula): SetDat( "BitPos" to 0) + SetDatRsz( "Data0" to "Selected Data" ) Initializes computation: 1- Sets Bit Pos to Zero. 2- Copies selected dataset into 'Data' This is an open object with a formula. As such, it only evaluates in response to explicit action by the user. |
Compute O2 Gen | Scalar | Not shown in solutions table. (Has Formula): Animate( "Bit Pos" @ "Bit Positions" by 0 until "Z" ) Runs the O2 Gen computation by causes global computations to repeat with "Bit Pos" set to the successive values contained in "Bit Positions". By 0 indicates to proceed at maximum speed. Iterations stop when "Z" goes positive (true). The Animate(...) function has two main uses in DataQube: 1 - To allow a dataset to be visualized over a time period or over a set of changing parameters. 2 - For implementing looping behavior in computations. It is used in the formula of an open object and only evaluates in response to explicit action by the user. In this case, it is coupled with feedback mimic recursion. |
Day 3B (CO2 Scrub) Solutions:
Table shows the state of the objects at the end of the computation.
# | Selected Data | Num Bits | Bit Positions | Bit Pos | Data0 | Half Sz | Current Bit | LCB | Retain | Z | Backfeed | Result Binary Array | Decimal Result | Final Product |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 00100 | 5 | 1 | 3 | 01111 | 1 | 1 | 0 | 01010 | 1 | 0 | 0 | 10 | 230 |
2 | 11110 | 2 | 01010 | 0 | 1 | |||||||||
3 | 10110 | 3 | 0 | |||||||||||
4 | 10111 | 4 | 1 | |||||||||||
5 | 10101 | 5 | 0 | |||||||||||
6 | 01111 | |||||||||||||
7 | 00111 | |||||||||||||
8 | 11100 | |||||||||||||
9 | 10000 | |||||||||||||
10 | 11001 | |||||||||||||
11 | 00010 | |||||||||||||
12 | 01010 |
Day 3B CO2 Scrub Narrative:
This solution is identical to the O2 Gen solution except that LCB (Least Common Bit) is substituted for MCB.
LCB = If(:Bit Pos" , (GSum("Current Bit") < "HalfSz") Else 0)
Day 4A Solution: (Bingo)
# | Selected Data | Sq Sz | Brd Sz | Draw Index | Draws | Brds | Num Brds | Brd Ndx | Row Ndx | Col Ndx | Draw Ndx | Draw | Mark Plays | Plays | Row Play Cnt | Brd Col | Col Play Cnt | Win Brd | Win Brd Score | Rslt |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25 | 3 | 9 | 1 | 7 | 22 | 3 | 1 | 1 | 1 | 10 | 14 | 0 | 0 | 1 | 11 | 0 | 1 | 64 | 896 |
2 | 2 | 4 | 13 | 1 | 1 | 2 | 0 | 12 | 2 | |||||||||||
3 | 22 13 17 | 3 | 9 | 17 | 1 | 1 | 3 | 1 | 13 | 3 | ||||||||||
4 | 8 2 23 | 4 | 5 | 8 | 1 | 2 | 1 | 0 | 2 | 11 | 0 | |||||||||
5 | 21 9 14 | 5 | 11 | 2 | 1 | 2 | 2 | 1 | 12 | 2 | ||||||||||
6 | 6 | 17 | 23 | 1 | 2 | 3 | 1 | 13 | 3 | |||||||||||
7 | 3 15 0 | 7 | 23 | 21 | 1 | 3 | 1 | 0 | 2 | 11 | 0 | |||||||||
8 | 9 18 13 | 8 | 2 | 9 | 1 | 3 | 2 | 1 | 12 | 2 | ||||||||||
9 | 19 8 7 | 9 | 0 | 14 | 1 | 3 | 3 | 1 | 13 | 3 | ||||||||||
10 | 10 | 14 | 3 | 2 | 1 | 1 | 0 | 1 | 21 | 1 | ||||||||||
11 | 14 21 17 | 11 | 21 | 15 | 2 | 1 | 2 | 0 | 22 | 0 | ||||||||||
12 | 10 16 15 | 12 | 24 | 0 | 2 | 1 | 3 | 1 | 23 | 2 | ||||||||||
13 | 18 8 23 | 13 | 10 | 9 | 2 | 2 | 1 | 1 | 1 | 21 | 1 | |||||||||
14 | 14 | 16 | 18 | 2 | 2 | 2 | 0 | 22 | 0 | |||||||||||
15 | 15 | 13 | 13 | 2 | 2 | 3 | 0 | 23 | 2 | |||||||||||
16 | 16 | 6 | 19 | 2 | 3 | 1 | 0 | 1 | 21 | 1 | ||||||||||
17 | 17 | 15 | 8 | 2 | 3 | 2 | 0 | 22 | 0 | |||||||||||
18 | 18 | 25 | 7 | 2 | 3 | 3 | 1 | 23 | 2 | |||||||||||
19 | 14 | 3 | 1 | 1 | 1 | 2 | 31 | 1 | ||||||||||||
20 | 21 | 3 | 1 | 2 | 0 | 32 | 0 | |||||||||||||
21 | 17 | 3 | 1 | 3 | 1 | 33 | 2 | |||||||||||||
22 | 10 | 3 | 2 | 1 | 0 | 0 | 31 | 1 | ||||||||||||
23 | 16 | 3 | 2 | 2 | 0 | 32 | 0 | |||||||||||||
24 | 15 | 3 | 2 | 3 | 0 | 33 | 2 | |||||||||||||
25 | 18 | 3 | 3 | 1 | 0 | 1 | 31 | 1 | ||||||||||||
26 | 8 | 3 | 3 | 2 | 0 | 32 | 0 | |||||||||||||
27 | 23 | 3 | 3 | 3 | 1 | 33 | 2 |
Day 4A Narrative:
Object | Type | Explanation |
---|---|---|
vSelected Data | List | Dataset selected for current computation. |
vSq Sz | Scalar | = SzOf(Pack(Parse( "vSelected Data" [3] by ' ') ) ) Size of boards (side). Computed from the first line of the first board. |
vBrd Sz | Scalar | = "vSq Sz" ^2 Number of places on a board. |
vDraws | Real Array | = Num(Parse( "vSelected Data" [1] by ',') ) Sequence of draws |
vDraw Index | Index | = NdxTo( "vDraws" ) Index to draw sequence. |
vBrds | Real Array | = Num(Pack(Parse( "vSelected Data" [2.. -1] by ' ') ) ) Boards in single column format. The selected data from line 2 to the end parsed into a single column. |
vNum Brds | Scalar | = SzOf( "vBrds" ) / "vBrd Sz" Number of Boards. |
vBrd Ndx | Index | = FlatFill(Inflate(Ndx( "vNum Brds" ) by "vBrd Sz" ) ) Indexes the boards "vBrds". |
vRow Ndx | Index | = Repeat( "vNum Brds" , FlatFill(Inflate(Ndx( "vSq Sz" ) by "vSq Sz" ) ) ) Indexes the rows in each board. |
vCol Ndx | Index | = Repeat( ( "vNum Brds" * "vSq Sz" ) , Ndx( "vSq Sz" ) ) Indexes the columns in each board. |
vDraw Ndx | Scalar | (Has Formula): 0 Current Draw index (iterated by loop). |
vDraw | Scalar | = "vDraws" [ "vDraw Ndx" ] Current draw. |
vPlays | Mask | (Has Formula): 0 Mask marking all plays. |
vMark Plays | Scalar | = If( ( "vDraw Ndx" > 0) , (SetDat( "vPlays" to ( "vPlays" or ( "vBrds" = "vDraw" ) ) ) ) ) Marks the plays. |
vRow Play Cnt | Real Array | = `GSum( "vPlays" ||| "vSq Sz" ) Count of plays in each row of each board. |
vBrd Col | Real Array | = Num(Txt( "vBrd Ndx" ) + Txt( "vCol Ndx" ) ) Global ID for each column of each board. (Used to sum by category) |
vCol Play Cnt | Real Array | = `SumOf( "vPlays" by "vBrd Col" ) Count of plays in each column of each board. (Note that there is full redundancy here as a result of the type of sum.) |
vWin Brd | Scalar | = ( "vBrd Ndx" [ ( "vRow Play Cnt" = "vSq Sz" ) or ( "vCol Play Cnt" = "vSq Sz" ) ][1] & 0) Winning board. Determined by extracting the indexes for all boards that have a full row or column, and taking the first of these - that is the winning board. Note that if there are multiple boards that win at the same time, only the first in th sequence is selected as the winner. |
vWin Brd Score | Scalar | = GSum(Num( "vBrds" ) [ ( "vBrd Ndx" = "vWin Brd" ) and Not( "vPlays" ) ]) Score of winning board. (Sum of unmarked places on board.) |
vRslt | Scalar | = "vDraw" * "vWin Brd Score" RESULT FOR PART A. |
vCompute 4A | Scalar | (Has Formula): Animate( "vDraw Ndx" @ "vDraw Index" by 0 until "vWin Brd" ) Iterates "vDraw Ndx" over the values in "vDraw Index" until there is a winning board. |
Day 4B Solution:
Table shows the state of the objects at the end of the computation.
# | Selected Data | Sq Sz | Brd Sz | Draw Index | Draws | Open Brds | Num Brds | Brd Ndx | Row Ndx | Col Ndx | Draw Ndx | Draw | Mark Plays | Plays | Row Play Cnt | Brd Col | Col Play Cnt | Num Win Brds | Stop | Win Brds | Win Brd Score | Rslt | Rem Mask | New Brds | New Brd Ndx | New Plays | Init |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25 | 3 | 9 | 1 | 7 | 3 | 1 | 2 | 1 | 1 | 15 | 13 | 0 | 0 | 1 | 21 | 1 | 1 | 1 | 2 | 63 | 819 | 0 | 0 | 0 | ||
2 | 2 | 4 | 15 | 2 | 1 | 2 | 0 | 22 | 0 | 0 | |||||||||||||||||
3 | 22 13 17 | 3 | 9 | 0 | 2 | 1 | 3 | 1 | 23 | 3 | 0 | ||||||||||||||||
4 | 8 2 23 | 4 | 5 | 9 | 2 | 2 | 1 | 1 | 2 | 21 | 1 | 0 | |||||||||||||||
5 | 21 9 14 | 5 | 11 | 18 | 2 | 2 | 2 | 0 | 22 | 0 | 0 | ||||||||||||||||
6 | 6 | 17 | 13 | 2 | 2 | 3 | 1 | 23 | 3 | 0 | |||||||||||||||||
7 | 3 15 0 | 7 | 23 | 19 | 2 | 3 | 1 | 0 | 1 | 21 | 1 | 0 | |||||||||||||||
8 | 9 18 13 | 8 | 2 | 8 | 2 | 3 | 2 | 0 | 22 | 0 | 0 | ||||||||||||||||
9 | 19 8 7 | 9 | 0 | 7 | 2 | 3 | 3 | 1 | 23 | 3 | 0 | ||||||||||||||||
10 | 10 | 14 | |||||||||||||||||||||||||
11 | 14 21 17 | 11 | 21 | ||||||||||||||||||||||||
12 | 10 16 15 | 12 | 24 | ||||||||||||||||||||||||
13 | 18 8 23 | 13 | 10 | ||||||||||||||||||||||||
14 | 14 | 16 | |||||||||||||||||||||||||
15 | 15 | 13 | |||||||||||||||||||||||||
16 | 16 | 6 | |||||||||||||||||||||||||
17 | 17 | 15 | |||||||||||||||||||||||||
18 | 18 | 25 |
Day 4B Narrative:
Object | Type | Explanation |
---|---|---|
vSelected Data vSq Sz vBrd Sz vDraw Index vDraws |
These are the same set of objects that part A uses as input. | |
xOpen Brds | Integer Array | Boards remaining in current iteration, in single column format. Object is open to allow backfeed of reduced board set at the start of each iteration. |
xNum Brds | Scalar | = SzOf( "xOpen Brds" ) / "vBrd Sz" Number of boards. |
xBrd Ndx | Index | (Has Formula): FlatFill(Inflate(Ndx( "vNum Brds" ) by "vBrd Sz" ) ) Indexes the boards in "xOpen Brds". The formula is used to initialize the object at the start. Object is open to allow backfeed of index to reduced board set at start of each iteration. |
xRow Ndx | Index | = Repeat( "xNum Brds" , FlatFill(Inflate(Ndx( "vSq Sz" ) by "vSq Sz" ) ) ) Indexes the rows in each board. |
xCol Ndx | Index | = Repeat( ( "xNum Brds" * "vSq Sz" ) , Ndx( "vSq Sz" ) ) Indexes the columns in each board. |
xDraw Ndx | Scalar | Current draw index. |
xDraw | Scalar | = "vDraws" [ "xDraw Ndx" ] Current draw. |
xMark Plays | Scalar | = If( ( "xDraw Ndx" > 0) , (SetDat( "xPlays" to ( "xPlays" or ( "xOpen Brds" = "xDraw" ) ) ) ) ) Marks the plays. |
xPlays | Mask | Mask marking all plays. |
xRow Play Cnt | Real Array | = `GSum( "xPlays" ||| "vSq Sz" ) Count of plays in each row of each board. |
xBrd Col | Real Array | = Num(Txt( "xBrd Ndx" ) + Txt( "xCol Ndx" ) ) Global ID for each column of each board. (Used to sum by category) |
xCol Play Cnt | Real Array | = `SumOf( "xPlays" by "xBrd Col" ) Count of plays in each column of each board. (Note that there is full redundancy here as a result of the type of sum.) |
xWin Brds | Real Array | = UniqVals( "xBrd Ndx" [ ( "xRow Play Cnt" = "vSq Sz" ) or ( "xCol Play Cnt" = "vSq Sz" ) ]) Winning boards in current cycle. |
xNum Win Brds | Scalar | = DatSz( "xWin Brds" ) Number of winning boards in current cycle. |
xStop | Scalar | = ( ( "xNum Brds" <= 1) and ( "xNum Win Brds" > 0) ) Stop indicator. |
xWin Brd Score | Scalar | = GSum(Num( "xOpen Brds" ) [ ( "xBrd Ndx" = "xWin Brds" [1]) and Not( "xPlays" ) ]) Score of winning board. (Sum of unmarked places on board.) |
xRslt | Scalar | = "xDraw" * "xWin Brd Score" THE RESULT FOR PART B. |
xRem Mask | Msk | = Not(MskTo( "xWin Brds" in "xBrd Ndx" ) ) Mask to remaining boards. |
xNew Brds | Integer Array | = If( ( "xNum Win Brds" > 0) , "xOpen Brds" [ "xRem Mask" ] Else "xOpen Brds" ) Remaining boards after winning boards are deleted. Backfed into "xOpen Brds" at start of each cycle. |
xNew Brd Ndx | Index | = If( ( "xNum Win Brds" > 0) , "xBrd Ndx" [ "xRem Mask" ] Else "xBrd Ndx" ) Board index corresponding to remaining boards. Backfed into "xBrd Ndx" at the start of each cycle. |
xNew Plays | Mask | = If( ( "xNum Win Brds" > 0) , "xPlays" [ "xRem Mask" ] Else "xPlays" ) Plays corresponding to remaining boards. Backfed into "xPlays" at the start of each cycle. |
xBackfeed | Real Array | = If( ( ( "xWin Brds" > 0) and ( "xNum Brds" > 1) ) , (SetDatRsz( "xOpen Brds Name" to "xNew Brds" ) + SetDatRsz( "xBrd Ndx Name" to "xNew Brd Ndx" ) + SetDatRsz( "xPlays Name" to "xNew Plays" ) ) ) Backfeeeds the data for the remaining boards, at the start of each cycle. |
xInit | Scalar | (Has Formula): SetDatRsz( "xOpen Brds Name" to "vBrds" ) + SetDat( "xDraw Ndx Name" to 0) + SetDatRsz( "xPlays Name" to Not(MskTo( "vBrds" ) ) ) Initializes the input objects in response to user action prior to computation. |
xCompute 4B | Scalar | (Has Formula): Animate( "xDraw Ndx" @ "vDraw Index" by 0 until "xStop" ) Performs the computation (iteration) in response to user action. |
Day 5 Solutions: (Hydrothermal Vents)
This solution computes unity x,y coordinates for all points in all of the line segments. The x,y coordinates are then encoded into single unique numerical identifiers for each location. A count is then made of all location identifiers that appear more than once. This is the count of intersections.
Numerical location identifiers are used instead of text representations of the x,y coordinate pairs in order to significantly speed up the counting process. (The search for intersections requires essentially the same number of comparisons as a full sort, so using numerics is much faster.)
# | Selected Data | X1 | Y1 | X2 | Y2 | Horz | Vert | X Span | Y Span | Vert X | Vert Y | Horz X | Horz Y | All Points A | Rslt A | Diag | Diag X | Diag Y | All Points B | Rslt B |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 8,0 -> 4,4 | 8 | 0 | 4 | 4 | 0 | 0 | 5 | 5 | 7 | 0 | 9 | 4 | 70000 | 6461 | 1 | 8 | 0 | 70000 | 18065 |
2 | 9,4 -> 3,4 | 9 | 4 | 3 | 4 | 1 | 0 | 7 | 1 | 7 | 1 | 8 | 4 | 70001 | 0 | 7 | 1 | 70001 | ||
3 | 7,0 -> 7,4 | 7 | 0 | 7 | 4 | 0 | 1 | 1 | 5 | 7 | 2 | 7 | 4 | 70002 | 0 | 6 | 2 | 70002 | ||
4 | 6,4 -> 4,2 | 6 | 4 | 4 | 2 | 0 | 0 | 3 | 3 | 7 | 3 | 6 | 4 | 70003 | 1 | 5 | 3 | 70003 | ||
5 | 7 | 4 | 5 | 4 | 70004 | 4 | 4 | 70004 | ||||||||||||
6 | 4 | 4 | 90004 | 6 | 4 | 90004 | ||||||||||||||
7 | 3 | 4 | 80004 | 5 | 3 | 80004 | ||||||||||||||
8 | 70004 | 4 | 2 | 70004 | ||||||||||||||||
9 | 60004 | 60004 | ||||||||||||||||||
10 | 50004 | 50004 | ||||||||||||||||||
11 | 40004 | 40004 | ||||||||||||||||||
12 | 30004 | 30004 | ||||||||||||||||||
13 | 80000 | |||||||||||||||||||
14 | 70001 | |||||||||||||||||||
15 | 60002 | |||||||||||||||||||
16 | 50003 | |||||||||||||||||||
17 | 40004 | |||||||||||||||||||
18 | 60004 | |||||||||||||||||||
19 | 50003 | |||||||||||||||||||
20 | 40002 |
Day 5 Narrative:
Object | Type | Explanation |
---|---|---|
aSelected Data | List | Dataset selected for the computation. |
aX1 | Array | = Extract#(1, "aSelected Data" ) X1 coordinates |
aY1 | Array | = Extract#(2, "aSelected Data" ) Y1 coordinates |
aX2 | Array | = Extract#(3, "aSelected Data" ) X2 coordinates |
aY2 | Array | = Extract#(4, "aSelected Data" ) Y2 coordinates |
aHorz | Mask | = "aY1" = "aY2" Maks to horizontal lines |
aVert | Mask | = "aX1" = "aX2" Mask to vertical lines |
aX Span | Array | = Abs( "aX2" - "aX1" ) + 1 Span of X coordinates in each line. |
aY Span | Array | = Abs( "aY2" - "aY1" ) + 1 Span of Y coordinates in each line. |
aVert X | Array | = FlatFill(Inflate( "aX1" [ "aVert" ] by "aY Span" [ "aVert" ]) ) X coordinates of all points in vertical lines. (For vertical lines X remains constant while Y changes stepwise.) |
aVert Y | Array | = Ndx( "aY1" [ "aVert" ].. "aY2" [ "aVert" ]) Y coordinates of all points in vertical lines. |
aHorz X | Array | = Ndx( "aX1" [ "aHorz" ].. "aX2" [ "aHorz" ]) X coordinates of all points in horizontal lines. (For horizontal lines, X changes stepwise while Y remains constant.) |
aHorz Y | Array | FlatFill(Inflate( "aY1" [ "aHorz" ] by "aX Span" [ "aHorz" ]) ) Y coordinates of all points in horizontal lines. |
aAll Points A | = Num( (Txt( "aVert X" ) + '000' + Txt( "aVert Y" ) ) ++ (Txt( "aHorz X" ) + '000' + Txt( "aHorz Y" ) Unique numerical location identifiers for all points in vertical and horizontal lines. The identifiers were configures as numeric in order to substantially reduce the computational time. With the full dataset, this is a rather large array and counting the unique values is computationally roughly equivalent to a full sort. This operation is much faster on numeric vs textual data. |
|
aRslt A | (Has Formula): GSum(UniqValCnts( "aAll Points A" ) > 1) THE RESULT FOR PART A. (The count of all points in vertical and horizontal lines that appear more than once.) This and "aRslt B" are configured as an open objects with formulae so that evaluation is explicitly user initiated. (Note long evaluation time with large dataset.) |
|
aDiag | = Abs( "aX2" - "aX1" ) = Abs( "aY2" - "aY1" ) Mask to diagonal lines. (For diagonal lines, the X and Y distances are equal.) |
|
aDiag X | = Ndx( "aX1" [ "aDiag" ].. "aX2" [ "aDiag" ]) X coordinates of all points in diagonal lines. (For diagonal lines, X and Y both change stepwise.) |
|
aDiag Y | = Ndx( "aY1" [ "aDiag" ].. "aY2" [ "aDiag" ]) Y coordinates of all points in diagonal lines. |
|
aAll Points B | = "aAll Points A" ++ Num( (Txt( "aDiag X" ) + '000' + Txt( "aDiag Y" ) ) ) Unique numerical location identifiers for all points in all lines. |
|
aRslt B | (Has Formula): GSum(UniqValCnts( "aAll Points B" ) > 1) THE RESULT FOR PART B. (The count of all points in all lines that appear more than once.) |
Day 6 Solution 1: (Lanternfish Population Growth)
This problem pretty much begs for recursion which DataQube is not capable of.
Computations in DQ involve operations on entire objects. Consequently, in order to follow the population growth over time, rather large arrays are generated. Though I have two solutions that handle the 80 day growth, I have been unable to keep the array sizes small enough to handle the 256 day growth.
This solution steps through the time period one day at a time, spawning new fish and reseting fish timers according to schedule. The result is the total population at the end.
Table shows state of data prior to computation.
# | Num Days | Selected Data | Step | Cur State | Zero Msk | Dec | Next State | Result |
---|---|---|---|---|---|---|---|---|
1 | 80 | 3 | 0 | 3 | 0 | 2 | 2 | 5 |
2 | 4 | 4 | 0 | 3 | 3 | |||
3 | 3 | 3 | 0 | 2 | 2 | |||
4 | 1 | 1 | 0 | 0 | 0 | |||
5 | 2 | 2 | 0 | 1 | 1 | |||
6 |
Day 6 Solution 1 Narrative:
Object | Type | Explanation |
---|---|---|
mSelected Data | Real Array | Dataset selected for the computation. |
mNum Days | Scalar | Number of days over which to grow population. |
mIteration Ndx | Index | = Ndx( "mNum Days" ) Used to step through computation one day at a time. Not shown in table. |
mStep | Scalar | Current day in computation. Initializes to 0. |
mCur State | Integer Array | Current state of population. (Counter values for all fish.) Initializes to "mSelected Data". |
mSero Msk | Mask | = "mCur State" = 0 Mask to counters in current state with value of zero. |
mDec | Real Array | = "mCur State" - 1 All counters in current state decremented by one. |
mNext State | Real Array | = Pack(6[ "mZero Msk" ] & "mDec" ) ++ Pack(8[ "mZero Msk" ]) State at start of next day. |
mBackfeed | = If( ( ( "mStep" > 0) and ( "mStep" <= "mNum Days" ) ) , (SetDatRsz( "mCur Dat Name" to "mNext State" ) ) ) Feeds the next population state (mNext State) back into mCur State. |
|
mResult | Scalar | = DatCnt( "mCur State" ) Total population at end of time period. |
mCompute | Scalar | (Has Formula): Animate( "mStep" @ "mIteration Ndx" by 0) Performs the iteration. Not shown in table. |
Day 6 Solution 2:
This solution steps through one generation at a time, recording the total # of spawns over the full time period for the generation, and computing the spawn dates for each. The spawn dates for one generation are then backfed as the birth dates for the next generation. The result is the sum of spawns in all generations plus the original population.
Table shows state at end of computation.
# | Selected Data | Gen0 Birth Dates | Gen | Cur Birth Dates | Cur Spawns | Cur Spawn Dates | Spawn Dates In Range | Num Spawns | Stop | Spawn Tally | Result |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 3 | -5 | 9 | 76 | 1 | 85 | 1 | 1 | 5934 | ||
2 | 4 | -4 | 77 | 1 | 86 | 57 | |||||
3 | 3 | -5 | 76 | 1 | 85 | 275 | |||||
4 | 1 | -7 | 74 | 1 | 83 | 825 | |||||
5 | 2 | -6 | 75 | 1 | 84 | 1530 | |||||
6 | 1470 | ||||||||||
7 | 1050 | ||||||||||
8 | 600 | ||||||||||
9 | 117 | ||||||||||
10 | 5 |
Day 6 Solution 2 Narrative:
Object | Type | Explanation |
---|---|---|
mSelected Data | Real Array | Dataset selected for the computation. |
oGen0 Birth Dates | Real Array | = "mSelected Data" - 8 Birth dates for generation 0. |
oGen | Scalar | Current generation. Initializes to -1. |
oCur Birth Dates | Integer Array | Birth dates for current generation. Initializes to "oGen0 Birth Dates" |
oCur Spawns | Real Array | = Int( ( "mNum Days" - "oCur Birth Dates" - 9) /7) + 1 Total number of spawns for each fish in current generation over full time period. |
oCur Spawn Dates | Real Array | = If( (GSum( "oCur Spawns" ) > 0) , NdxFill(Inflate( ( "oCur Birth Dates" + 8) by "oCur Spawns" ) by 7) + 1) Spawn dates for all fish in current generation. |
oSpawn Dates In Range | Real Array | = "oCur Spawn Dates" [ "oCur Spawn Dates" <= "mNum Days" ] Spawn dates that will occur before end of time period. |
oNum Spawns | Scalar | = SzOf( "oSpawn Dates In Range" ) Total number of spawns for current generation. |
oStop | Scalar | = DatSz( "oSpawn Dates In Range" ) = 0 |
oSpawn Tally | Real Array | Total number of fish spawned in each generation. Updated on each iteration by "oBackfeed". Initializes to empty array. |
oBackfeed | Scalar | = If( ( ( "oGen" >= 0) and Not( "oStop" ) ) , (SetDatRsz(GetProp(Name of "oCur Birth Dates" ) to "oSpawn Dates In Range" ) + SetDatRsz(GetProp(Name of "oSpawn Tally" ) to ( "oSpawn Tally" ++ "oNum Spawns" ) ) ) ) Not shown in table. |
oResult | Scalar | = GSum( "oSpawn Tally" ) + DatSz( "oGen0 Birth Dates" ) Total population at end of time period. |
oCompute | Scalar | (Has Formula): Animate( "oGen" @ "mIteration Ndx" by 0 until "oStop" ) Performs the iteration. Not shown in table. |
Day 6 Solution 3:
Well, I failed the exam miserably with solutions 1 and 2.
This solution starts with the counts of fish in each age group and steps through the days. On each iteration, the timers for all fish are decremented, the group of fish with zero timers spawns a set of juveniles, and the 2-day old juveniles are added to the adult population counts.
This solution generates no large arrays.
## | Selected Data | Sorted Data | Gen0 Timers | Gen0 Counts | Timer Vals | Start | Adults | Juveniles | Add | Step A | Step B | Total Count | Num Days | Day |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 3 | 1 | 1 | 1 | 0 | 0 | 2376852196 | 0 | 0 | 2731163883 | 0 | 26,984,457,539 | 256 | 256 |
2 | 4 | 2 | 2 | 1 | 1 | 1 | 2731163883 | 0 | 0 | 2897294544 | 0 | |||
3 | 3 | 3 | 3 | 2 | 2 | 1 | 2897294544 | 0 | 0 | 3164316379 | 0 | |||
4 | 1 | 3 | 4 | 1 | 3 | 2 | 3164316379 | 0 | 0 | 3541830408 | 0 | |||
5 | 2 | 4 | 4 | 1 | 3541830408 | 0 | 0 | 3681986557 | 0 | |||||
6 | 5 | 0 | 3681986557 | 0 | 0 | 4275812629 | 0 | |||||||
7 | 6 | 0 | 2329711392 | 1946101237 | 1 | 2376852196 | 1985489551 | |||||||
8 | 7 | 1985489551 | 2329711392 | |||||||||||
9 | 8 | 2329711392 | 2376852196 |
Day 6 Solution 3 Narrative:
Object | Type | Explanation |
---|---|---|
mSelected Data | Real Array | Dataset selected for computation. |
ySorted Data | Real Array | = Sort( "mSelected Data" ) Sorted dataset. (The datatset is sorted so that the initial population counts come out in order of age class.) |
yGen0 Timers | Index | = AsNdx(UniqVals( "ySorted Data" ) ) Generation 0 timers. |
yGen0 Counts | Integer Array | = UniqValCnts( "ySorted Data" ) Generation 0 counts of each age group. |
yTimer Vals | Real Array | = Ndx(9) - 1 The full set of timer values. |
yStart | Real Array | = Inflate( "yGen0 Counts" to 7 by ( "yGen0 Timers" + 1) ) & 0 Starting state of population distribution (the fish counts corresponding to each timer value). |
yAdults | Real Array | (Has Formula): "yStart" (This initializes the object.) Adult counts. (Updated on each iteration by the "yStep".) |
yJuveniles | Real Array | (Has Formula): Not(MskTo( "yTimer Vals" ) ) (This initializes the object to all zeros.) Juvenile counts. (Updated on each iteration by the "yStep".) |
yAdd | Mask | This is a static mask used as a marker for adding matured juveniles into adult count. |
yStep A | Real Array | = ShiftWrap( ( "yAdults" + ( "yJuveniles" `[ "yAdd" ] & 0) [1..7]) by -1) Adds matured juveniles to Adult counts and decrements counters (by shifting data up one). |
yStep B | Real Array | = (Shift( "yJuveniles" by -1) & "yAdults" [1]) `[7..End] & 0 Shifts juvenile counts up one retaining counts only for juveniles that have not matured. |
yTotal Count | Scalar | = GSum( "yAdults" ) + GSum( "yJuveniles" ) Sums up total population. |
mNum Days | Scalar | Number of days over which to grow population. |
yDay | Scalar | (Has Formula): 0 (This initializes the object.) Current day in the iteration. |
yNdx | Index | = Ndx( "mNum Days" ) Iteration index. Not shown in table. |
yStep | Scalar | = If( ( "yDay" > 0) , (SetDat(GetProp(Name of "yAdults" ) to "yStep A" ) + SetDat(GetProp(Name of "yJuveniles" ) to "yShift B" ) ) ) Updates the Adult and Juvenile count arrays on each iteration. Not shown in table. |
yCompute 6-3 | Scalar | (Has Formula): Animate( "yDay" @ "yNdx" by 0) Performs the iteration. Not shown in table. |
Day 7 Solution 1: (Least Fuel Consumption)
This solution analyzes the entire dataset at once (no iteration).
The table shows only the first 18 of 119 lines.
# | Selected Data | Unique Pos | Cnts | Num Pos | Num Unique Pos | To Pos | Exp Data | Exp Cnts | Dist | Fuel Lookup | Fuel A | Min Fuel A | Target Pos A | Fuel B | Min Fuel B | Target Pos B |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 16 | 16 | 1 | 17 | 7 | 0 | 16 | 1 | 16 | 1 | 49 | 37 | 2 | 290 | 168 | 5 |
2 | 1 | 1 | 2 | 0 | 1 | 2 | 1 | 3 | ||||||||
3 | 2 | 2 | 3 | 0 | 2 | 3 | 2 | 6 | ||||||||
4 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 10 | ||||||||
5 | 4 | 4 | 1 | 0 | 4 | 1 | 4 | 15 | ||||||||
6 | 2 | 7 | 1 | 0 | 7 | 1 | 7 | 21 | ||||||||
7 | 7 | 14 | 1 | 0 | 14 | 1 | 14 | 28 | ||||||||
8 | 1 | 1 | 16 | 1 | 15 | 36 | 41 | 242 | ||||||||
9 | 2 | 1 | 1 | 2 | 0 | 45 | ||||||||||
10 | 14 | 1 | 2 | 3 | 1 | 55 | ||||||||||
11 | 1 | 0 | 1 | 1 | 66 | |||||||||||
12 | 1 | 4 | 1 | 3 | 78 | |||||||||||
13 | 1 | 7 | 1 | 6 | 91 | |||||||||||
14 | 1 | 14 | 1 | 13 | 105 | |||||||||||
15 | 2 | 16 | 1 | 14 | 120 | 37 | 206 | |||||||||
16 | 2 | 1 | 2 | 1 | 136 | |||||||||||
17 | 2 | 2 | 3 | 0 | ||||||||||||
18 | 2 | 0 | 1 | 2 |
(Note that the "Fuel Lookup" array is not correspondent to the other arrays.)
Day 7 Solution 1 Narrative:
Object | Type | Explanation |
---|---|---|
pSelected Data | Real Array | Selected dataset (positions of all the crabs.) |
pUnique Pos | Real Array | = UniqVals( "pSelected Data" ) Unique occupied positions. |
pCnts | Integer Array | = UniqValCnts( "pSelected Data" ) Number of crabs at each position. |
pNum Pos | Scalar | = GMax( "pSelected Data" ) + 1 Total number of positions. |
pNum Unique Pos | Scalar | = SzOf( "pUnique Pos" ) Number of unique occupied positions. |
pTo Pos | Real Array | = FlatFill(Inflate( (Ndx( "pNum Pos" ) - 1) by "pNum Unique Pos" ) ) Array of all possible target positions expanded to accommodate a repetition of occupied positions. |
pExp Data | Real Array | = Repeat( "pNum Pos" , "pUnique Pos" ) Array of occupied positions repeated to correlate with the "To Pos" array. |
pExp Cnts | Integer Array | = Repeat( "pNum Pos" , "pCnts" ) Expanded array of crab counts at each position. |
pDist | Real Array | = Abs( "pExp Data" - "pTo Pos" ) Distance of each occupied position to target position. |
pFuel Lookup | Real Array | = CSum(Ndx(GMax( "pDist" ) ) ) Lookup array of Part B fuel required for each distance except 0. (The cumulative sum of an index the size of the largest distance traversed.) (Used only for part B - for part A, the fuel required is just the distance.) |
pFuel A | Real Array | = `GSum( ( "pDist" * "pExp Cnts" ) ||| GrpsAltMsk( "pTo Pos" ) ) Part A fuel required for all crabs to move to each of the target position. |
pMin Fuel A | Scalar | = GMin( "pFuel A" ) Part A minimum fuel consumed. |
pTarget Pos A | Real Array | = "pTo Pos" [ "pFuel A" = "pMin Fuel A" ] |
pFuel B | Real Array | = `GSum( ( "pFuel Lookup" [ "pDist" ] * "pExp Cnts" ) ||| GrpsAltMsk( "pTo Pos" ) ) Part B fuel required for all crabs to move to each of the target position. |
pMin Fuel B | Scalar | = GMin( "pFuel B" ) Part B minimum fuel consumed. |
pTarget Pos B | Real Array | = "pTo Pos" [ "pFuel B" = "pMin Fuel B" ] Part B target position corresponding to minimum fuel consumption |
Day 7 Solution 2:
This solution iterates through the dataset starting at position 0, proceeding until the minimums of both position vs fuel consumption curves are reached. Though this solution processes less data, it is much slower to execute since DQ evaluates the entire object train at each iteration.
Table shows state at end of computation.
# | Selected Data | Unique Pos | Cnts | Iteration Ndx | To Pos | Stop A | Stop B | Stop All | Dist | Dist+ | Fuel Lookup | Fuel A | Fuel B | Set A Rslts | Set B Rslts | Rslt A | Rslt B |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 16 | 16 | 1 | 1 | 5 | 1 | 1 | 1 | 11 | 10 | 1 | 0 | 0 | 2 | 5 | ||
2 | 1 | 1 | 2 | 2 | 4 | 5 | 3 | 37 | 168 | ||||||||
3 | 2 | 2 | 3 | 3 | 3 | 4 | 6 | ||||||||||
4 | 0 | 0 | 1 | 4 | 5 | 6 | 10 | ||||||||||
5 | 4 | 4 | 1 | 5 | 1 | 2 | 15 | ||||||||||
6 | 2 | 7 | 1 | 6 | 2 | 1 | 21 | ||||||||||
7 | 7 | 14 | 1 | 7 | 9 | 8 | 28 | ||||||||||
8 | 1 | 8 | 36 | ||||||||||||||
9 | 2 | 9 | 45 | ||||||||||||||
10 | 14 | 10 | 55 | ||||||||||||||
11 | 11 | 66 | |||||||||||||||
12 | 12 | ||||||||||||||||
13 | 13 | ||||||||||||||||
14 | 14 | ||||||||||||||||
15 | 15 | ||||||||||||||||
16 | 16 |
Day 7 Solution 2 Narrative:
# | Object | Type | Explanation |
---|---|---|---|
1 | pSelected Data | Real Array | Selected data (positions of all the crabs) |
2 | pUnique Pos | Real Array | = UniqVals( "pSelected Data" ) Unique occupied positions. |
3 | pCnts | Integer Array | = UniqValCnts( "pSelected Data" ) Number of crabs at each position. |
4 | sIteration Ndx | Index | = Ndx(GMax( "pSelected Data" ) ) Index for iterating 'To Pos'. |
5 | sTo Pos | Scalar | Target position for current iteration. Initialized to -1. Incremented at each iteration. |
6 | sStop A | Scalar | Stop indicator for part A computation. Initialized to 0, goes to 1 when part A minimum is found. |
7 | sStop B | Scalar | Stop indicator for part B computation. Initialized to 0, goes to 1 when part B minimum is found. |
8 | sStop All | Scalar | = "sStop A" and "sStop B" Stop indicator for entire computation. |
9 | sDist | Real Array | = Abs( "pUnique Pos" - "sTo Pos" ) Distance of each occupied position from the current target position. |
10 | sDist+ | Real Array | = Abs( "pUnique Pos" - ( "sTo Pos" + 1) ) Distance of each occupied position from next target position. |
11 | sFuel Lookup | Real Array | = CSum(Ndx(GMax( "sDist" ) ) ) Lookup array of fuel required for each distance except 0. |
12 | sFuel A | Real Array | = If(Not( "sStop A" ) , (GSum( "sDist" * "pCnts" ) ++ GSum( "sDist+" * "pCnts" ) ) Else Array(2) ) Part A fuel required for all crabs to move to current and next target positions. |
13 | sFuel B | Real Array | = If(Not( "sStop B" ) , (GSum( "sFuel Lookup" [ "sDist" ] * "pCnts" ) ++ GSum( "sFuel Lookup" [ "sDist+" ] * "pCnts" ) ) Else Array(2) ) Part B fuel required for all crabs to move to current and next target positions. |
14 | sSet A Rslts | Scalar | = If( (Not( "sStop A" ) and ( "sFuel A" [1] < "sFuel A" [2]) ) , (SetDat(GetProp(Name of "sRslt A" ) to ( "sTo Pos" ++ "sFuel A" [1]) ) + SetDat(GetProp(Name of "sStop A" ) to 1) ) Else 0) Sets A Results and A stop when A Fuel requirement starts to increase. |
15 | sSet B Rslts | Scalar | = If( (Not( "sStop B" ) and ( "sFuel B" [1] < "sFuel B" [2]) ) , (SetDat(GetProp(Name of "sRslt B" ) to ( "sTo Pos" ++ "sFuel B" [1]) ) + SetDat(GetProp(Name of "sStop B" ) to 1) ) Else 0) Sets B Results and B stop when B Fuel requirement starts to increase. |
16 | sRslt A | Integer Array | Part A result (target position, fuel consumption). |
17 | sRslt B | Integer Array | Part B result (target position, fuel consumption). |
18 | sCompute 7-2 | Scalar | (Has Formula): Animate( "sTo Pos" @ "sIteration Ndx" by 0 until "sStop All" ) Performs the iteration. Not shown in table. |
Day 8 Solution: (Decoding Digital Display Output)
This solution, though conceptually simple, required a rather large number of computational steps.
The solution takes advantage of the fact that, for each set of observations (each line in the dataset), the full set of observed signal patterns is given. The problem is then finding which map produces that set of patterns from the known correct set of patterns.
For the full dataset, staring with a 7 character string representing the 7 segment identifiers, an array of mappings is generated that transforms that string into all possible arrangements of the 7 characters. (This results in an array of 5040 different possible mappings.)
Those mappings are then applied to the set of correct signal patterns to generate all possible unique sets of the 10 output signal patterns.
These sets of signal patterns are then compared to the observed set of patterns to determine which is the correct mapping for that set of observations.
The ordered set of transformed patterns is extracted from that mapping output, and the corresponding digit values are then determined.
(Note that in the example below, the full dataset is not used. Instead, a very abbreviated dataset is used - a single data line with 5 observed patterns (corresponding to digits 0-4) with a maximum of 4 segments.)
Table 1: (Partial)
# | Obs0 | Output0 | Segs0 | Vld Ptrns0 | Digits | Num Segs | Num Ptrns | All Segs | Exp1 | Exp2 | Exp3 | Exp4 | It Ndx | Record Results |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | acd | ac | a | abd | 0 | 4 | 5 | abcd | a | a | a | a | 1 | 0 |
2 | abd | abcd | b | acd | 1 | a | a | a | b | |||||
3 | ac | acd | c | ab | 2 | a | a | a | c | |||||
4 | bd | d | cd | 3 | a | a | a | d | ||||||
5 | abcd | abcd | 4 | a | a | b | a | |||||||
6 | a | a | b | b | ||||||||||
7 | a | a | b | c | ||||||||||
8 | a | a | b | d | ||||||||||
9 | a | a | c | a | ||||||||||
10 | a | a | c | b | ||||||||||
11 | a | a | c | c | ||||||||||
12 | a | a | c | d | ||||||||||
13 | a | a | d | a | ||||||||||
14 | a | a | d | b | ||||||||||
15 | a | a | d | c | ||||||||||
16 | a | a | d | d | ||||||||||
17 | a | b | a | a | ||||||||||
18 | a | b | a | b | ||||||||||
19 | a | b | a | c | ||||||||||
20 | a | b | a | d |
Table 2: (Partial)
# | Combined | Red Msk | Reduced | Map In | Map Out | Map Groups | Map#s | Infl Vld Ptrns | Exp Ndx0 | Exp Ndx1 | Exp Ndx2 | Exp Map# | Infl Map In | Infl Map Out | Exp Vld Ptrns | Coded Ptrns 0 | Vld Ptrns | Coded Ptrns 1 | Coded Ptrns 2 | Code Map# | Line# | Obs | Output | Coded Ptrns Input Msk | Num Ptrn Matches | Map# | Digits | Coded Output | Rslt | Rslts | Rslt Sum |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | aaaa | 0 | abcd | a | a | 0 | 1 | abd | 1 | 1 | 4 | 1 | a | a | abd | a | abd | abd | abd | 1 | 1 | acd | ac | 1 | 3 | 3 | 0 | acd | 240 | 240 | |
2 | aaab | 0 | abdc | b | b | 0 | 1 | abd | 5 | 1 | 4 | 1 | b | b | abd | b | acd | acd | acd | 1 | abd | abcd | 1 | 1 | abd | ||||||
3 | aaac | 0 | acbd | c | c | 0 | 1 | abd | 9 | 1 | 4 | 1 | c | c | abd | ab | ab | ab | 1 | ac | acd | 0 | 2 | ac | 240 | ||||||
4 | aaad | 0 | acdb | d | d | 0 | 1 | abd | 13 | 1 | 4 | 1 | d | d | abd | d | cd | cd | cd | 1 | bd | 0 | 3 | bd | |||||||
5 | aaba | 0 | adbc | a | a | 1 | 2 | acd | 17 | 1 | 4 | 1 | a | a | acd | a | abcd | abcd | abcd | 1 | abcd | 1 | 4 | abcd | |||||||
6 | aabb | 0 | adcb | b | b | 1 | 2 | acd | 21 | 5 | 8 | 1 | b | b | acd | abd | abc | abc | 2 | 0 | 2 | ||||||||||
7 | aabc | 0 | bacd | c | d | 1 | 2 | acd | 25 | 5 | 8 | 1 | c | c | acd | c | acd | adc | acd | 2 | 1 | ||||||||||
8 | aabd | 0 | badc | d | c | 1 | 2 | acd | 29 | 5 | 8 | 1 | d | d | acd | d | ab | ab | ab | 2 | 0 | ||||||||||
9 | aaca | 0 | bcad | a | a | 0 | 3 | ab | 33 | 5 | 8 | 1 | a | a | ab | a | cd | dc | cd | 2 | 0 | ||||||||||
10 | aacb | 0 | bcda | b | c | 0 | 3 | ab | 37 | 5 | 8 | 1 | b | b | ab | b | abcd | abdc | abcd | 2 | 1 | ||||||||||
11 | aacc | 0 | bdac | c | b | 0 | 3 | ab | 41 | 9 | 12 | 1 | c | c | ab | abd | acd | acd | 3 | 1 | 5 | ||||||||||
12 | aacd | 0 | bdca | d | d | 0 | 3 | ab | 45 | 9 | 12 | 1 | d | d | ab | acd | abd | abd | 3 | 1 | |||||||||||
13 | aada | 0 | cabd | a | a | 1 | 4 | cd | 49 | 9 | 12 | 1 | a | a | cd | ab | ac | ac | 3 | 1 | |||||||||||
14 | aadb | 0 | cadb | b | c | 1 | 4 | cd | 53 | 9 | 12 | 1 | b | b | cd | cd | bd | bd | 3 | 1 | |||||||||||
15 | aadc | 0 | cbad | c | d | 1 | 4 | cd | 57 | 9 | 12 | 1 | c | c | cd | c | abcd | acbd | abcd | 3 | 1 | ||||||||||
16 | aadd | 0 | cbda | d | b | 1 | 4 | cd | 61 | 13 | 16 | 1 | d | d | cd | d | abd | acb | abc | 4 | 0 | 4 | |||||||||
17 | abaa | 0 | cdab | a | a | 0 | 5 | abcd | 65 | 13 | 16 | 1 | a | a | abcd | a | acd | adb | abd | 4 | 1 | ||||||||||
18 | abab | 0 | cdba | b | d | 0 | 5 | abcd | 69 | 13 | 16 | 1 | b | b | abcd | b | ab | ac | ac | 4 | 1 | ||||||||||
19 | abac | 0 | dabc | c | b | 0 | 5 | abcd | 73 | 13 | 16 | 1 | c | c | abcd | c | cd | db | bd | 4 | 1 | ||||||||||
20 | abad | 0 | dacb | d | c | 0 | 5 | abcd | 77 | 13 | 16 | 1 | d | d | abcd | d | abcd | acdb | abcd | 4 | 1 | ||||||||||
21 | abba | 0 | dbac | a | a | 1 | 6 | 81 | 17 | 20 | 2 | a | a | abd | a | abd | adc | acd | 5 | 1 | 2 | ||||||||||
22 | abbb | 0 | dbca | b | d | 1 | 6 | 85 | 17 | 20 | 2 | b | b | abd | b | acd | abc | abc | 5 | 0 | |||||||||||
23 | abbc | 0 | dcab | c | c | 1 | 6 | 89 | 17 | 20 | 2 | c | d | abd | ab | ad | ad | 5 | 0 | ||||||||||||
24 | abbd | 0 | dcba | d | b | 1 | 6 | 93 | 17 | 20 | 2 | d | c | abd | c | cd | bc | bc | 5 | 0 | |||||||||||
25 | abca | 0 | a | b | 0 | 7 | 17 | 20 | 2 | a | a | acd | a | abcd | adbc | abcd | 5 | 1 | |||||||||||||
26 | abcb | 0 | b | a | 0 | 7 | 21 | 24 | 2 | b | b | acd | abd | adb | abd | 6 | 1 | 2 | |||||||||||||
27 | abcc | 0 | c | c | 0 | 7 | 21 | 24 | 2 | c | d | acd | d | acd | acb | abc | 6 | 0 | |||||||||||||
28 | abcd | 1 | d | d | 0 | 7 | 21 | 24 | 2 | d | c | acd | c | ab | ad | ad | 6 | 0 | |||||||||||||
29 | abda | 0 | a | b | 1 | 8 | 21 | 24 | 2 | a | a | ab | a | cd | cb | bc | 6 | 0 | |||||||||||||
30 | abdb | 0 | b | a | 1 | 8 | 21 | 24 | 2 | b | b | ab | b | abcd | adcb | abcd | 6 | 1 | |||||||||||||
31 | abdc | 1 | c | d | 1 | 8 | 25 | 28 | 2 | c | d | ab | abd | bad | abd | 7 | 1 | 2 | |||||||||||||
32 | abdd | 0 | d | c | 1 | 8 | 25 | 28 | 2 | d | c | ab | acd | bcd | bcd | 7 | 0 |
Day 8 Narrative:
Object | Type | Explanation |
---|---|---|
wObs0 | List | Set of Observed patterns. This example was produced using a very abbreviated dataset - a single data line with 5 observed patterns (corresponding to digits 0-4) with a maximum of 4 segments. |
wOutput0 | List | The set of output paterns (for a 3 digit display). |
wSegs0 | List | The list of display segments. |
wVld Ptrns0 | List | The ordered set of valid segment compbinations used to render the digits on the display. |
wDigits | Integer Array | = Int(Ndx(SzOf( "wVld Ptrns0" ) ) - 1) Digits corresponding to the segment patterns. |
wNum Segs | Scalar | = SzOf( "wSegs0" ) Number of physical segments in a display. |
wNum Ptrns | Scalar | = SzOf( "wVld Ptrns0" ) Number of segment patterns used for rendering individual digits. |
wAll Segs | String | = GSum( "wSegs0" ) All segments combined into one string. |
wExp1, wExp2, wExp3, wExp4 | Lists | = EXPAND(n, wSegs0, wSegs0, wSegs0, wSegs0) (Where n = 1,2,3,4 in successive definitions.) A series of four objects that, taken together, form the expanded set of all combinations of the fouyr segments a,b,c,d. |
wIt Ndx | Index | = Ndx(GMax( "wLine#" ) ) Iteration index. (Because this dataset has only one line of data, this is an index of one.) |
xCombined | List | = wExp1 + wExp2 + wExp3 + wExp4 All possible combinations of segment identifiers. (Including repetitions) |
xRed Msk | Mask | = ArrOf?( "xCombined" of "wAll Segs" ) Reduction mask (Mask to only the combinations that are re-arrangements of the full set of segment identifiers.) |
xReduced | List | = "xCombined" [ "xRed Msk" ] All possible arrangements of the full set of segment identifiers. |
xMap In | List | = Repeat(SzOf( "xReduced" ) , "wSegs0" ) The input for each mapping - the set of segment identifiers repeated once for each map. |
xMap Out | List | = Parse( "xReduced" by '') The output for each mapping - all possible arrangements of the map inputs. |
xMap Groups | Mask | = AltMsk(SzOf( "xMap In" ) by "wNum Segs" ) Alternating mask delineating each map. |
xMap#s | Integer Array | = GrpCds( "xMap Groups" ) Map numbers. |
xInfl Vld Ptrns | List | = RepeatVals( "wVld Ptrns0" by "wNum Segs" ) "wVld Ptrns0" with each pattern repeated by the number of segments. |
xExp Ndx0 | Index | = Ndx(1.. (SzOf( "xMap In" ) ) by "wNum Segs" ) Index for inflating the mappings by the number of segments. |
xExp Ndx1 | Index | = FlatFill(Inflate( "xExp Ndx0" by "wNum Ptrns" ) ) Start index for inflating the mappings by the number of valid patterns. |
xExp Ndx2 | Index | = "xExp Ndx1" + "wNum Segs" - 1 End index for inflating the mappings by the number of valid patterns. |
xExp Map# | Integer Array | = "xMap#s" [ "xExp Ndx1" .. "xExp Ndx2" ] Full expansion of "xMap #s". |
xInfl Map In | List | = "xMap In" [ "xExp Ndx1" .. "xExp Ndx2" ] Full expansion of "xMap In". |
xInfl Map Out | List | = "xMap Out" [ "xExp Ndx1" .. "xExp Ndx2" ] Full expansion of "xMap Out". |
xExp Vld Ptrns | List | = Fill(SzOf( "xInfl Map In" ) , "xInfl Vld Ptrns" ) Full expansion of display segment patterns. |
xCoded Ptrns 0 | List | = "xInfl Map Out" `[StrIn?( "xInfl Map In" in "xExp Vld Ptrns" ) ] Individual Mapped segments for each of the diplay segment patterns. |
xVld Ptrns | List | = GMin( "xExp Vld Ptrns" ||| "wNum Segs" ) The set of valid display segment patterns repeated for each map. |
xCoded Ptrns 1 | List | = GSum( "xCoded Ptrns 0" ||| "wNum Segs" ) Raw output for each map |
xCoded Ptrns 2 | List | = SortTxt( "xCoded Ptrns 1" by "xCoded Ptrns 1" ) Segment sorted output for each map. |
xCode Map# | Real Array | = GAve( "xExp Map#" ||| "wNum Segs" ) Map numbers. |
xLine# | Scalar | (Has Formula): 0 (This initializes the object.) Selects the data line for the current iteration. (In this case there is only one data line.) |
xObs | List | = "wObs0" [ "wLine#" = "xLine#" ] Observed patterns for the current iteration. |
xOutput | List | = Pack( "wOutput0" [ "wLine#" = "xLine#" ]) Currently selected output patterns. |
xCoded Ptrns Input Msk | Mask | = MskTo( "xObs" in "xCoded Ptrns 2" ) Mask indicating where the observed patterns are present in the code patterns. |
xNum Ptrn Matches | Real Array | = `GSum( "xCoded Ptrns Input Msk" ||| "wNum Ptrns" ) Number of matches in each pattern set. |
xMap# = | Scalar | = ( "xCode Map#" [ "xNum Ptrn Matches" = "wNum Ptrns" ]) [1] Map # of the map with a full set of matches. |
xCoded Output | List | = "xCoded Ptrns 2" [ "xCode Map#" = "xMap#" ] The full set of coded patterns from the current map in order of corresponding digit. |
xRslt | Scalar | = Num(GSum(Txt( "wDigits" [NdxToFirst( "xOutput" in "xCoded Output" ) ]) ) ) The output display value for the current map. |
xRslts | Integer Array | (Has Formula): Array(1) (This initializes the object.) Array of all the output values (one for each line of data.) |
wRecord Results | Scalar | = SetDatRsz(GetProp(Name of "xRslts" ) to ( "xRslts" ++ "xRslt" ) ) Records the result from each iteration into the results array. |
xRslt Sum | Scalar | = GSum( "xRslts" ) The sum of all results. |
wCompute 8 | Scalar | (Has Formula): Animate( "xLine#" @ "wIt Ndx" by 0) Performs the iteration. |
Day 9A Solution: (Smoke Basins)
For part A, viewing the array of elevations as a matrix, the minima were found in each row and in each column separately, and the coordinates were noted for each of these. The basin bottoms, then were the points for which row and columns minima coincided.
The table shows the solution for a very small dataset.
# | Selected Data | Num Rows | Num Cols | Row Dat | Row X | Row Y | Row Coords | Row Low Pts Msk | To Col Ndx | Col Dat | Col X | Col Y | Col Coords | Col Low Pts Msk | Low Pt Coords | Low Pt Vals | IS Coords | IS Vals | Score |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2199943 | 4 | 7 | 2 | 1 | 1 | 101 | 0 | 1 | 2 | 1 | 1 | 101 | 1 | 201 | 1 | 201 | 1 | 19 |
2 | 3987894 | 1 | 2 | 1 | 201 | 1 | 8 | 3 | 1 | 2 | 102 | 0 | 701 | 3 | 701 | 3 | |||
3 | 9856789 | 9 | 3 | 1 | 301 | 0 | 15 | 9 | 1 | 3 | 103 | 0 | 102 | 3 | 303 | 5 | |||
4 | 8767896 | 9 | 4 | 1 | 401 | 0 | 22 | 8 | 1 | 4 | 104 | 1 | 402 | 7 | 704 | 6 | |||
5 | 9 | 5 | 1 | 501 | 0 | 2 | 1 | 2 | 1 | 201 | 1 | 702 | 4 | ||||||
6 | 4 | 6 | 1 | 601 | 0 | 9 | 9 | 2 | 2 | 202 | 0 | 303 | 5 | ||||||
7 | 3 | 7 | 1 | 701 | 1 | 16 | 8 | 2 | 3 | 203 | 0 | 304 | 6 | ||||||
8 | 3 | 1 | 2 | 102 | 1 | 23 | 7 | 2 | 4 | 204 | 1 | 704 | 6 | ||||||
9 | 9 | 2 | 2 | 202 | 0 | 3 | 9 | 3 | 1 | 301 | 0 | 101 | 2 | ||||||
10 | 8 | 3 | 2 | 302 | 0 | 10 | 8 | 3 | 2 | 302 | 0 | 104 | 8 | ||||||
11 | 7 | 4 | 2 | 402 | 1 | 17 | 5 | 3 | 3 | 303 | 1 | 201 | 1 | ||||||
12 | 8 | 5 | 2 | 502 | 0 | 24 | 6 | 3 | 4 | 304 | 0 | 204 | 7 | ||||||
13 | 9 | 6 | 2 | 602 | 0 | 4 | 9 | 4 | 1 | 401 | 0 | 303 | 5 | ||||||
14 | 4 | 7 | 2 | 702 | 1 | 11 | 7 | 4 | 2 | 402 | 0 | 403 | 6 | ||||||
15 | 9 | 1 | 3 | 103 | 0 | 18 | 6 | 4 | 3 | 403 | 1 | 503 | 7 | ||||||
16 | 8 | 2 | 3 | 203 | 0 | 25 | 7 | 4 | 4 | 404 | 0 | 601 | 4 | ||||||
17 | 5 | 3 | 3 | 303 | 1 | 5 | 9 | 5 | 1 | 501 | 0 | 603 | 8 | ||||||
18 | 6 | 4 | 3 | 403 | 0 | 12 | 8 | 5 | 2 | 502 | 0 | 701 | 3 | ||||||
19 | 7 | 5 | 3 | 503 | 0 | 19 | 7 | 5 | 3 | 503 | 1 | 704 | 6 | ||||||
20 | 8 | 6 | 3 | 603 | 0 | 26 | 8 | 5 | 4 | 504 | 0 | ||||||||
21 | 9 | 7 | 3 | 703 | 0 | 6 | 4 | 6 | 1 | 601 | 1 | ||||||||
22 | 8 | 1 | 4 | 104 | 0 | 13 | 9 | 6 | 2 | 602 | 0 | ||||||||
23 | 7 | 2 | 4 | 204 | 0 | 20 | 8 | 6 | 3 | 603 | 1 | ||||||||
24 | 6 | 3 | 4 | 304 | 1 | 27 | 9 | 6 | 4 | 604 | 0 | ||||||||
25 | 7 | 4 | 4 | 404 | 0 | 7 | 3 | 7 | 1 | 701 | 1 | ||||||||
26 | 8 | 5 | 4 | 504 | 0 | 14 | 4 | 7 | 2 | 702 | 0 | ||||||||
27 | 9 | 6 | 4 | 604 | 0 | 21 | 9 | 7 | 3 | 703 | 0 | ||||||||
28 | 6 | 7 | 4 | 704 | 1 | 28 | 6 | 7 | 4 | 704 | 1 |
Day 9A Narrative:
Object | Type | Explanation |
---|---|---|
ccSelected Data | List | Selected Data (Array of elevations - each line contains a series of elevations in the range 0..9) |
ccNum Rows | Scalar | = DatSz( "ccSelected Data" ) Number of rows in the elevation matrix. |
ccNum Cols | Scalar | = TxtLen( "ccSelected Data" [1]) Number of columns in the elevation matrix. |
ccRow Dat | Real Array | = Num(Parse( "ccSelected Data" by '') ) Elevation data grouped by row. |
ccRow X | Integer Array | = GrpCellNdx( "ccRow Grps" ) X coordinates for row data. |
ccRow Y | Integer Array | = GrpCds( "ccRow Grps" ) Y coordinates for row data. |
ccRow Coords | Real Array | = Num(Txt( "ccRow X" ) + '0' + Txt( "ccRow Y" ) ) Coded X,Y coordinates for row data. |
ccRow Low Pts Msk | Mask | = ( "ccRow Dat" < (Shift( "ccRow Dat" by -1 ||| "ccNum Cols" ) & 9) ) and ( "ccRow Dat" < (Shift( "ccRow Dat" by 1 ||| "ccNum Cols" ) & 9) ) Mask to low points in row data. |
ccTo Col Ndx | Index | = IncrFill(Inflate(Ndx( "ccNum Cols" ) by "ccNum Rows" ) by "ccNum Cols" ) Index for transforming data in row format to column format. |
ccCol Dat | Real Array | = "ccRow Dat" [ "ccTo Col Ndx" ] Elevation data grouped by column. |
ccCol X | Integer Array | = "ccRow X" [ "ccTo Col Ndx" ] X coordinates for column data. |
ccCol Y | Integer Array | = "ccRow Y" [ "ccTo Col Ndx" ] Y coordinates for column data. |
ccCol Coords | Real Array | = Num(Txt( "ccCol X" ) + '0' + Txt( "ccCol Y" ) ) Coded X,Y coordinates for column data. |
ccCol Low Pts Msk | Mask | = ( "ccCol Dat" < (Shift( "ccCol Dat" by -1 ||| "ccNum Rows" ) & 9) ) and ( "ccCol Dat" < (Shift( "ccCol Dat" by 1 ||| "ccNum Rows" ) & 9) ) Mask to low points in column data. |
ccLow Pt Coords | Real Array | = "ccRow Coords" [ "ccRow Low Pts Msk" ] ++ "ccCol Coords" [ "ccCol Low Pts Msk" ] Coordinates of all low points in row data and column data combined. |
ccLow Pt Vals | Real Array | = "ccRow Dat" [ "ccRow Low Pts Msk" ] ++ "ccCol Dat" [ "ccCol Low Pts Msk" ] Height values corresponding to all low points. |
ccIS Coords | Real Array | = UniqVals( "ccLow Pt Coords" [Dups?( "ccLow Pt Coords" ) ]) Intersection coordinates. |
ccScore | Scalar | = GSum( "ccIS Vals" + 1) Total risk score. |
Day 9B Solution:
For part B, the irregularity of the boundaries presents a significant problem for DQ. Poking around within the bounded areas to find and count the points belonging to each basin requires a multitude of individual comparisons in no particular order or pattern. As DQ cannot do recursion or nested loops, and allows for only one level of iteration, this approach would be very tedious if even possible.
The only practical approach to dealing with large 2 dimensional arrays in DQ is with a one dimensional representation in which all the rows (or columns) are incorporated into a single column with each row (or column) following the preceding one. Consequently, the points belonging to any particular basin (2 dimensional area) occupy non-contiguous segments in the dataset. The only practical way to resolve the basins, then is to assign a unique value to the points in each basin.
The solution used here is to first assign a set of ever increasing integral values to all points in the matrix, starting in one corner, and proceeding row by row through the entire matrix so that each point has a unique value, and the span of values is roughly 10* the number of points in the array.
An iteration is then used to repeatedly average the values in each segment between the ridges in each column followed by the same in each row. By this method, eventually, for each basin, all the points in the basin are averaged to the same value. If the total span of starting values is great enough, then each basin ends up with a unique value. With all the basins completely resolved, the number of points in each is then be counted.
The table for part B shows the solution for the same small dataset as in part A.
# | Row Basin Msk | Row Grps | Row Grp Codes | Row Full Alt Msk | Col Basin Msk | Col Full Allt Msk | To Row Ndx | Initial | Start | By Col | Ave Vert | By Row | Ave Horz | Step | Num Points Rem | Stop | Basin Sizes | Rslt | Progress | Basin Colors |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 5 | 336.343 | 336.3 | 336.8 | 336.8 | 336.586 | 5 | 0 | 1 | 3 | 117 | 0 | 4.67 |
2 | 1 | 0 | 0 | 1 | 1 | 1 | 5 | 5 | 336.343 | 337.3 | 336.8 | 336.3 | 336.586 | 3 | 1 | 4.67 | ||||
3 | 0 | 0 | 0 | 0 | 0 | 0 | 9 | 30 | 30.000 | 2000.0 | 2000.0 | 30.0 | 30.000 | 13 | 1 | 0.42 | ||||
4 | 0 | 0 | 0 | 0 | 1 | 1 | 13 | 30 | 30.000 | 2180.2 | 2180.2 | 30.0 | 30.000 | 1 | 1 | 0.42 | ||||
5 | 0 | 0 | 0 | 0 | 1 | 0 | 17 | 30 | 30.000 | 336.3 | 336.3 | 30.0 | 30.000 | 1 | 0.42 | |||||
6 | 1 | 0 | 0 | 1 | 0 | 1 | 21 | 55 | 389.673 | 1010.0 | 1010.0 | 389.7 | 389.918 | 1 | 5.41 | |||||
7 | 1 | 0 | 0 | 1 | 1 | 0 | 25 | 55 | 389.673 | 2179.9 | 2180.0 | 390.2 | 389.918 | 1 | 5.41 | |||||
8 | 1 | 1 | 1000 | 0 | 1 | 0 | 2 | 1000 | 337.314 | 2180.2 | 2180.0 | 336.8 | 336.829 | 1 | 4.68 | |||||
9 | 0 | 1 | 1000 | 1 | 0 | 1 | 6 | 1010 | 1010.000 | 30.0 | 30.0 | 1010.0 | 1010.000 | 1 | 14.03 | |||||
10 | 1 | 1 | 1000 | 0 | 1 | 0 | 10 | 1030 | 2179.952 | 2180.0 | 2180.0 | 2180.0 | 2179.994 | 1 | 30.28 | |||||
11 | 1 | 1 | 1000 | 0 | 1 | 0 | 14 | 1030 | 2179.952 | 2179.9 | 2180.0 | 2180.0 | 2179.994 | 1 | 30.28 | |||||
12 | 1 | 1 | 1000 | 0 | 1 | 0 | 18 | 1030 | 2179.952 | 2180.2 | 2180.0 | 2180.0 | 2179.994 | 1 | 30.28 | |||||
13 | 0 | 1 | 1000 | 1 | 0 | 1 | 22 | 1050 | 1050.000 | 30.0 | 30.0 | 1050.0 | 1050.000 | 1 | 14.58 | |||||
14 | 1 | 1 | 1000 | 0 | 1 | 0 | 26 | 1060 | 390.654 | 2180.0 | 2180.0 | 390.2 | 390.164 | 1 | 5.43 | |||||
15 | 0 | 0 | 2000 | 1 | 1 | 0 | 3 | 2000 | 2000.000 | 2179.9 | 2180.0 | 2000.0 | 2000.000 | 1 | 27.78 | |||||
16 | 1 | 0 | 2000 | 0 | 1 | 0 | 7 | 2030 | 2179.856 | 2180.2 | 2180.0 | 2180.0 | 2179.970 | 1 | 30.28 | |||||
17 | 1 | 0 | 2000 | 0 | 0 | 1 | 11 | 2030 | 2179.856 | 30.0 | 30.0 | 2180.0 | 2179.970 | 1 | 30.28 | |||||
18 | 1 | 0 | 2000 | 0 | 1 | 0 | 15 | 2030 | 2179.856 | 2180.0 | 2180.0 | 2180.0 | 2179.970 | 1 | 30.28 | |||||
19 | 1 | 0 | 2000 | 0 | 1 | 0 | 19 | 2030 | 2179.856 | 2179.9 | 2180.0 | 2180.0 | 2179.970 | 1 | 30.28 | |||||
20 | 1 | 0 | 2000 | 0 | 1 | 0 | 23 | 2030 | 2179.856 | 2180.2 | 2180.0 | 2179.9 | 2179.970 | 1 | 30.28 | |||||
21 | 0 | 0 | 2000 | 1 | 1 | 1 | 27 | 2060 | 2060.000 | 389.7 | 389.7 | 2060.0 | 2060.000 | 1 | 28.61 | |||||
22 | 1 | 1 | 3000 | 0 | 0 | 0 | 4 | 3020 | 2180.173 | 1050.0 | 1050.0 | 2180.2 | 2180.034 | 1 | 30.28 | |||||
23 | 1 | 1 | 3000 | 0 | 1 | 1 | 8 | 3020 | 2180.173 | 2179.9 | 2179.9 | 2180.0 | 2180.034 | 1 | 30.28 | |||||
24 | 1 | 1 | 3000 | 0 | 0 | 0 | 12 | 3020 | 2180.173 | 3050.0 | 3050.0 | 2180.0 | 2180.034 | 1 | 30.28 | |||||
25 | 1 | 1 | 3000 | 0 | 1 | 1 | 16 | 3020 | 2180.173 | 389.7 | 390.2 | 2180.0 | 2180.034 | 1 | 30.28 | |||||
26 | 1 | 1 | 3000 | 0 | 1 | 1 | 20 | 3020 | 2180.173 | 390.7 | 390.2 | 2180.0 | 2180.034 | 1 | 30.28 | |||||
27 | 0 | 1 | 3000 | 1 | 0 | 0 | 24 | 3050 | 3050.000 | 2060.0 | 2060.0 | 3050.0 | 3050.000 | 1 | 42.36 | |||||
28 | 1 | 1 | 3000 | 0 | 1 | 1 | 28 | 3060 | 3060.000 | 3060.0 | 3060.0 | 3060.0 | 3060.000 | 1 | 42.50 |
The following video shows the part B solution for the full dataset.
The basin codes were scaled to span the full range of DQ accessible color numbers. At the start, the full range of colors appears as gradients across each row and proceeding from row to row. For the full dataset, basins appear to resolve early in the iteration, but full resolution does not occur until near the end. Iterations conclude at step 303. Note that the table is filtered to show only unresolved data lines (lines in which the basin values at the start and end of the iteration differed by more than the specified threshold). At the end of iterations, all data is filtered out of the table.
Day 9B Narrative:
Object | Type | Explanation |
---|---|---|
Part B uses several of the objects from Part A, which are not included in the table for Part B. | ||
eeRow Basin Msk | Mask | = "ccRow Dat" < 9 Mask pointing to the basin points in the row data. |
ccRow Grps | Mask | = AltMsk(ParseSzs( "ccSelected Data" by '') ) Alternating mask delineating row groupings in the row data. |
eeRow Grp Codes | Real Array | = ( "ccRow Y" - 1) * 1000 Row code values for initial encodeing. |
eeRow Full Alt Msk | Mask | = GrpsAltMsk( "eeRow Basin Msk" + "eeRow Grp Codes" ) Alternating mask flipping at each transition point in the row data. (Transition points are: Basin>Ridge, Ridge>Basin, New Row.) |
eeCol Basin Msk | Mask | = "ccCol Dat" < 9 Mask pointing to the basin points in the column data. |
eeCol Full Allt Msk | Mask | = GrpsAltMsk( "eeCol Basin Msk" + "ccCol X" * 2) Alternating mask flipping at each transition point in the column data. (Transition points are: Basin>Ridge, Ridge>Basin, New Column.) |
eeTo Row Ndx | Index | = IncrFill(Inflate(Ndx( "ccNum Rows" ) by "ccNum Cols" ) by "ccNum Rows" ) Index for transforming data in column format to row format. |
eeInitial | Integer Array | = FlatFill(Rnd(`GAve( ( ( "ccRow X" - 1) * 10 + "eeRow Grp Codes" ) ||| "eeRow Full Alt Msk" ) ) ) Initial encoding of basin and ridge traverses by row. Codes increase by 10 for each basin/ridge crossing, and by 100 at each new row juncture. |
eeStart | Real Array | (Has Formula): "eeInitial" |
eeBy Col | Real Array | = "eeStart" [ "ccTo Col Ndx" ] Encodings grouped by column. |
eeAve Vert | Real Array | = FlatFill(`GAve( "eeBy Col" ||| "eeCol Full Allt Msk" ) ) Averages of encodings within each basin vertical traverse in the column data. |
eeBy Row | Real Array | = "eeAve Vert" [ "eeTo Row Ndx" ] |
eeAve Horz | Real Array | = FlatFill(`GAve( "eeBy Row" ||| "eeRow Full Alt Msk" ) ) Averages of encodings within each basin horizontal traverse in the row data. |
eeStep | Scalar | (Has Formula): 0 Current iteration step. |
eeNum Points Rem | Scalar | = GSum(Not( "eeProgress" [2..End]) ) Number of unresolved points remaining. |
eeStop | Scalar | = GMin(Abs( "eeAve Horz" - "eeStart" ) < .5) |
eeBasin Sizes | Integer Array | = If( "eeStop" , UniqValCnts(Rnd( "eeAve Horz" ) [ "eeRow Basin Msk" ]) Else Array(1) ) The count of each unique value in the basin encoding data. (At the end of the iterations, each basin will have its own integral encoding value.) |
eeRslt | Scalar | = If( ( "eeStep" > 0) , GProd(Rev(Sort( "eeBasin Sizes" ) ) [1..3]) Else 0) Final Result. |
eeProgress | Mask | = AsMsk( ( "eeRow Basin Msk" `[1]) & (Abs( "eeAve Horz" - "eeStart" ) < 0.5) ) Mask indicating basin encodings that are fully reduced. (The inverse of this mask is used to filter the table. It is defined to keep the first row and unresolved encodings visible.) |
eeBasin Colors | Real Array | = "eeStart" /72 Used to show the progress on the map as basins are resolved. (DQ uses a discrete set of colors that can be accessed by integral base 10 identifiers. When colors are accessed via ) |
eeIT Ndx | Index | = Ndx(1000) Index used to iterate the "eeStep". (Not shown in table.) |
eeCompute 9B | Scalar | (Has Formula): Animate( "eeStep" @ "eeIT Ndx" by 0 until "eeStop" ) Performs the iteration. (Not shown in table.) |
eeBackfeed | Scalar | = If( ( "eeStep" > 0) , SetDat(GetProp(Name of "eeStart" ) to "eeAve Horz" ) ) (Not shown in table.) |
Day 10A Solution: (Syntax Scoring)
For part A, legal open/close pairs are repeatedly removed from the data until none are left.
The first remaining closing character then, is the first illegal character.
# | Selected Data | Op | Cl | Pairs | A Scores | B Scores | Closes | Max Num Pairs | It Ndx | Step | Start | Reduced | Corrupt | Pos | Bad Char | Total Score |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | [({(<(())[]>[[{[]{<()<>> | ( | ) | () | 3 | 1 | )]}> | 12 | 1 | 12 | [({([[{{ | [({([[{{ | 0 | 26397 | ||
2 | [(()[<>])]({[<{<<[]>>( | [ | ] | [] | 57 | 2 | 2 | ({[<{( | ({[<{( | 0 | ||||||
3 | {([(<{}[<>[]}>{[]{[(<()> | { | } | {} | 1197 | 3 | 3 | {([(<[}>{{[( | {([(<[}>{{[( | 1 | 7 | } | ||||
4 | (((({<>}<{<{<>}{[]{[]{} | < | > | <> | 25137 | 4 | 4 | ((((<{<{{ | ((((<{<{{ | 0 | ||||||
5 | [[<[([]))<([[{}[[()]]] | 5 | [[<[)<([ | [[<[)<([ | 1 | 5 | ) | |||||||||
6 | [{[{({}]{}}([{[{{{}}([] | 6 | [{[{(]}([{[{( | [{[{(]}([{[{( | 1 | 6 | ] | |||||||||
7 | {<[[]]>}<{[{[{[]{()[[[] | 7 | <{[{[{{[[ | <{[{[{{[[ | 0 | |||||||||||
8 | [<(<(<(<{}))><([]([]() | 8 | [<(<(<(<))><(( | [<(<(<(<))><(( | 1 | 9 | ) | |||||||||
9 | <{([([[(<>()){}]>(<<{{ | 9 | <{([([>(<<{{ | <{([([>(<<{{ | 1 | 7 | > | |||||||||
10 | <{([{{}}[<[[[<>{}]]]>[]] | 10 | <{([ | <{([ | 0 | |||||||||||
11 | 11 | |||||||||||||||
12 | 12 |
Day 10A Narrative:
Object | Type | Explanation |
---|---|---|
nnSelected Data | List | Dataset selected for computaion. |
nnOp | List | List of Open characters. |
nnCl | List | List of Close characters. |
nnPairs | List | = "nnOp" + "nnCl" The legal open/close character pairs. |
nnA Scores | Integer Array | Character scores for part A. |
nnB Scores | Integer Array | = Ndx(4) Character scores for part B |
nnCloses | String | = GSum( "nnCl" ) A string containing the four close characters. |
nnMax Num Pairs | Scalar | = Up(GMax(TxtLen( "nnSelected Data" ) ) /2) Maximum number of character pairs in a line. |
nnIt Ndx | Index | = Ndx( "nnMax Num Pairs" ) Iteration index. |
nnStep | Scalar | (Has Formula): 0 (Used for initialization) Current iteration step. |
nnStart | List | (Has Formula): "nnSelected Data" (Used for initialization) Data at the start of each iteration. |
nnReduced | List | = Sep(ExclMultStrs( "nnPairs" in "nnStart" ) ) The data in "nnStart" with the legal character pairs removed. |
nnBackfeed | Scalar | = If( ( "nnStep" > 0) , SetDat(GetProp(Name of "nnStart" ) to "nnReduced" ) ) Feeds the reduced data back into "Start" after each iteration. |
nnCompute 10A | Scalar | (Has Formula): Animate( "nnStep" @ "nnIt Ndx" by 0) Performs the iteration. |
nnCorrupt | Mask | = ChrIn?( "nnCloses" in "nnReduced" ) Marks the corrupt data lines.(Data lines with one or more close characters remaining after all legal pairs have been removed.) (Only valid after iteration.) |
nnPos | Real Array | = Min(StrStart(')' in "nnReduced" ) , StrStart(']' in "nnReduced" ) , StrStart('}' in "nnReduced" ) , StrStart('>' in "nnReduced" ) ) Position of first ilegal character in each fully reduced line. |
nnBad Char | List | = "nnReduced" { "nnPos" } First ilegal character in each fully reduced line. |
nnTotal Score | Scalar | = GSum(Code( "nnCl" in "nnBad Char" with "nnA Scores" ) ) Sum of line scores. |
Day 10B Solution:
After discarding the corrupt lines, the remaining lines each contain a sequence of opening characters. In each line, the sequence is reversed and then the corresponding closing characters are substituted. These are the sequences of characters needed to complete the lines. The closing sequences are then scored and the median score is found.
# | Open Sequence | Close Sequence | Parsed Close Sequences | Parsed Close Groups | Char Scores | Exponents | Line Scores | Final Score |
---|---|---|---|---|---|---|---|---|
1 | [({([[{{ | }}]])})] | } | 0 | 3 | 7 | 288957 | 288,957 |
2 | ({[<{( | )}>]}) | } | 0 | 3 | 6 | ||
3 | ((((<{<{{ | }}>}>)))) | ] | 0 | 2 | 5 | ||
4 | <{[{[{{[[ | ]]}}]}]}> | ] | 0 | 2 | 4 | ||
5 | <{([ | ])}> | ) | 0 | 1 | 3 | ||
6 | } | 0 | 3 | 2 | ||||
7 | ) | 0 | 1 | 1 | ||||
8 | ] | 0 | 2 | 0 | ||||
9 | ) | 1 | 1 | 5 | 5566 | |||
10 | } | 1 | 3 | 4 | ||||
11 | > | 1 | 4 | 3 | ||||
12 | ] | 1 | 2 | 2 | ||||
13 | } | 1 | 3 | 1 | ||||
14 | ) | 1 | 1 | 0 | ||||
15 | } | 0 | 3 | 8 | 1480781 | |||
16 | } | 0 | 3 | 7 | ||||
17 | > | 0 | 4 | 6 | ||||
18 | } | 0 | 3 | 5 | ||||
19 | > | 0 | 4 | 4 | ||||
20 | ) | 0 | 1 | 3 | ||||
21 | ) | 0 | 1 | 2 | ||||
22 | ) | 0 | 1 | 1 | ||||
23 | ) | 0 | 1 | 0 | ||||
24 | ] | 1 | 2 | 8 | 995444 | |||
25 | ] | 1 | 2 | 7 | ||||
26 | } | 1 | 3 | 6 | ||||
27 | } | 1 | 3 | 5 | ||||
28 | ] | 1 | 2 | 4 | ||||
29 | } | 1 | 3 | 3 | ||||
30 | ] | 1 | 2 | 2 | ||||
31 | } | 1 | 3 | 1 | ||||
32 | > | 1 | 4 | 0 | ||||
33 | ] | 0 | 2 | 3 | 294 | |||
34 | ) | 0 | 1 | 2 | ||||
35 | } | 0 | 3 | 1 | ||||
36 | > | 0 | 4 | 0 |
Day 10B Narrative:
Object | Type | Explanation |
---|---|---|
ooOpen Sequence | List | = "nnReduced" [Not( "nnCorrupt" ) ] Reduced data with corrupt lines removed. (The reduced non-corrupt lines contain only the unpaired open characters.) |
ooClose Sequence | List | = RevTxt(ReplMultStrs( "nnOp" in "ooOpen Sequence" with "nnCl" ) ) Closing charcter sequences needed to complete non-corrupt data lines. |
ooParsed Close Sequences | List | = Parse( "ooClose Sequence" by '') Close sequences parsed into a single list. |
ooParsed Close Groups | Mask | = AltMsk(ParseSzs( "ooClose Sequence" by '') ) Alternating mask delineating the groupings in "Parsed Close Sequences". |
ooChar Scores | Index | = Code( "nnCl" in "ooParsed Close Sequences" with "nnB Scores" ) Scores corresponding to the characters in "Parsed CloseSequences". |
ooExponents | Real Array | = Rev( (GrpDatTly( "ooParsed Close Groups" ) - 1) ||| "ooParsed Close Groups" ) The line scores are determined as follows: For a line of four characters in the order a,b,c,d, the line score is computed sequentially as: First: a then: 5a+b then: 5(5a+b)+c then: 5(5(5a+b)+c)+d The last line of above (the final score) is equivalent to: 5^3*a + 5^2*b + 5^1*c + 5^0*d (For each line, the exponents of 5 form a reverse index ending in zero.) |
ooLine Scores | Real Array | = `GSum( ( "ooChar Scores" * 5^ "ooExponents" ) ||| "ooParsed Close Groups" ) The line scores are computed as the sum of the character scores X 5 raised to the corresponding power. |
ooFinal Score | Scalar | = GMedn( "ooLine Scores" ) The final score is the median line score. |
Day 11 Solution: (Flashing Octopus)
This solution converts the input data into a single one dimensional data array in which the successive data columns follow one after another. A "Neighbor Position" (NP) array is then generated of the indices of all of the nearest neighbors for each position in the data array. An iteration is then run to step through array states over time.
The table shows only the first 25 of 800 lines.
# | Selected Data | Row Dat | Dat Grps | SqSz | Mtrx Sz | To Col Ndx | Dat Ndx | Col# | Row# | Row Y | Col Dat | NP Ndx | NP Grps | NP Row# | NP Col# | Rel NP | NP0 | In Range | Test Top | Test Bot | NP | Start | Start+ | Flash Msk | Boost | Inc Step | End | Sym Color | Txt Dat | Sym Sz | Loop | Step | Flash Cnt | Stop | Inc Step Cnt | Inc Flash Cnt |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1443582148 | 1 | 0 | 10 | 100 | 1 | 1 | 1 | 1 | 10 | 1 | 1 | 1 | 1 | 1 | -1 | 0 | 0 | 0 | 1 | 1 | 2 | 0 | 2 | 1 | 2 | 710 | 2 | 0.3 | 0 | 1 | 0 | 0 | 0 | 0 | |
2 | 6553734851 | 4 | 0 | 11 | 2 | 1 | 2 | 9 | 6 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 2 | 6 | 7 | 0 | 7 | 7 | 760 | 7 | 0.8 | |||||||||
3 | 1451741246 | 4 | 0 | 21 | 3 | 1 | 3 | 8 | 1 | 1 | 1 | 1 | 1 | -9 | -8 | 0 | 1 | 1 | 1 | 2 | 0 | 2 | 2 | 710 | 2 | 0.3 | ||||||||||
4 | 8835218864 | 3 | 0 | 31 | 4 | 1 | 4 | 7 | 8 | 1 | 1 | 1 | 1 | -10 | -9 | 0 | 1 | 1 | 8 | 9 | 0 | 9 | 9 | 780 | 9 | 1 | ||||||||||
5 | 1662317262 | 5 | 0 | 41 | 5 | 1 | 5 | 6 | 1 | 1 | 1 | 1 | 1 | -11 | -10 | 0 | 0 | 1 | 1 | 2 | 0 | 2 | 2 | 710 | 2 | 0.3 | ||||||||||
6 | 1731656623 | 8 | 0 | 51 | 6 | 1 | 6 | 5 | 1 | 1 | 1 | 1 | 1 | 9 | 10 | 1 | 0 | 1 | 1 | 2 | 0 | 2 | 2 | 710 | 2 | 0.3 | ||||||||||
7 | 1128178367 | 2 | 0 | 61 | 7 | 1 | 7 | 4 | 1 | 1 | 1 | 1 | 1 | 10 | 11 | 1 | 1 | 1 | 11 | 1 | 2 | 0 | 2 | 2 | 710 | 2 | 0.3 | |||||||||
8 | 5842351665 | 1 | 0 | 71 | 8 | 1 | 8 | 3 | 5 | 1 | 1 | 1 | 1 | 11 | 12 | 1 | 1 | 1 | 12 | 5 | 6 | 0 | 6 | 6 | 750 | 6 | 0.7 | |||||||||
9 | 6677326843 | 4 | 0 | 81 | 9 | 1 | 9 | 2 | 6 | 2 | 0 | 2 | 1 | -1 | 1 | 1 | 1 | 1 | 1 | 6 | 7 | 0 | 7 | 7 | 760 | 7 | 0.8 | |||||||||
10 | 7381433267 | 8 | 0 | 91 | 10 | 1 | 10 | 1 | 7 | 2 | 0 | 2 | 1 | 1 | 3 | 1 | 1 | 1 | 3 | 7 | 8 | 0 | 8 | 8 | 770 | 8 | 0.9 | |||||||||
11 | 6 | 1 | 2 | 11 | 2 | 1 | 10 | 4 | 2 | 0 | 2 | 1 | -9 | -7 | 0 | 1 | 1 | 4 | 5 | 0 | 5 | 5 | 740 | 5 | 0.6 | |||||||||||
12 | 5 | 1 | 12 | 12 | 2 | 2 | 9 | 5 | 2 | 0 | 2 | 1 | -10 | -8 | 0 | 1 | 1 | 5 | 6 | 0 | 6 | 6 | 750 | 6 | 0.7 | |||||||||||
13 | 5 | 1 | 22 | 13 | 2 | 3 | 8 | 4 | 2 | 0 | 2 | 1 | -11 | -9 | 0 | 1 | 1 | 4 | 5 | 0 | 5 | 5 | 740 | 5 | 0.6 | |||||||||||
14 | 3 | 1 | 32 | 14 | 2 | 4 | 7 | 8 | 2 | 0 | 2 | 1 | 9 | 11 | 1 | 1 | 1 | 11 | 8 | 9 | 0 | 9 | 9 | 780 | 9 | 1 | ||||||||||
15 | 7 | 1 | 42 | 15 | 2 | 5 | 6 | 6 | 2 | 0 | 2 | 1 | 10 | 12 | 1 | 1 | 1 | 12 | 6 | 7 | 0 | 7 | 7 | 760 | 7 | 0.8 | ||||||||||
16 | 3 | 1 | 52 | 16 | 2 | 6 | 5 | 7 | 2 | 0 | 2 | 1 | 11 | 13 | 1 | 1 | 1 | 13 | 7 | 8 | 0 | 8 | 8 | 770 | 8 | 0.9 | ||||||||||
17 | 4 | 1 | 62 | 17 | 2 | 7 | 4 | 1 | 3 | 1 | 3 | 1 | -1 | 2 | 1 | 1 | 1 | 2 | 1 | 2 | 0 | 2 | 2 | 710 | 2 | 0.3 | ||||||||||
18 | 8 | 1 | 72 | 18 | 2 | 8 | 3 | 8 | 3 | 1 | 3 | 1 | 1 | 4 | 1 | 1 | 1 | 4 | 8 | 9 | 0 | 9 | 9 | 780 | 9 | 1 | ||||||||||
19 | 5 | 1 | 82 | 19 | 2 | 9 | 2 | 6 | 3 | 1 | 3 | 1 | -9 | -6 | 0 | 1 | 1 | 6 | 7 | 0 | 7 | 7 | 760 | 7 | 0.8 | |||||||||||
20 | 1 | 1 | 92 | 20 | 2 | 10 | 1 | 3 | 3 | 1 | 3 | 1 | -10 | -7 | 0 | 1 | 1 | 3 | 4 | 0 | 4 | 4 | 730 | 4 | 0.5 | |||||||||||
21 | 1 | 0 | 3 | 21 | 3 | 1 | 10 | 4 | 3 | 1 | 3 | 1 | -11 | -8 | 0 | 1 | 1 | 4 | 5 | 0 | 5 | 5 | 740 | 5 | 0.6 | |||||||||||
22 | 4 | 0 | 13 | 22 | 3 | 2 | 9 | 5 | 3 | 1 | 3 | 1 | 9 | 12 | 1 | 1 | 1 | 12 | 5 | 6 | 0 | 6 | 6 | 750 | 6 | 0.7 | ||||||||||
23 | 5 | 0 | 23 | 23 | 3 | 3 | 8 | 5 | 3 | 1 | 3 | 1 | 10 | 13 | 1 | 1 | 1 | 13 | 5 | 6 | 0 | 6 | 6 | 750 | 6 | 0.7 | ||||||||||
24 | 1 | 0 | 33 | 24 | 3 | 4 | 7 | 3 | 3 | 1 | 3 | 1 | 11 | 14 | 1 | 1 | 1 | 14 | 3 | 4 | 0 | 4 | 4 | 730 | 4 | 0.5 | ||||||||||
25 | 7 | 0 | 43 | 25 | 3 | 5 | 6 | 6 | 4 | 0 | 4 | 1 | -1 | 3 | 1 | 1 | 1 | 3 | 6 | 7 | 0 | 7 | 7 | 760 | 7 | 0.8 |
Day 11 Narrative:
Objects | Type | Explanation |
---|---|---|
aSelected Data | List | Dataset selected for the computation. |
aRow Dat | Integer Array | = Rnd(Num(Parse( "aSelected Data" by '') ) ) Parsed row energy data. |
aDat Grps | Mask | = AltMsk(ParseSzs( "aSelected Data" by '') ) Groupings in energy data array (either column or row, since the data is a square matrix). |
aSqSz | Scalar | = SzOf( "aSelected Data" ) Size of data matrix. |
aMtrx Sz | Scalar | = "aSqSz" ^2 Number of elements in matrix. |
aTo Col Ndx | Index | = IncrFill(Inflate(Ndx( "aSqSz" ) by "aSqSz" ) by "aSqSz" ) Index for transposing row grouped data into column grouped data. |
aDat Ndx | Index | = NdxTo( "aRow Dat" ) Index to the data array (either column or row, since the array is the same size either way). |
aCol# | Integer Array | = GrpCds( "aDat Grps" ) Column # in the column data. In addition to its computaional function, aCol# is used as the X coordinate for plotting energies on the graph. |
aRow# | Integer Array | = GrpDatTly( "aDat Grps" ) Row # in the column data. |
aRow Y | Integer Array | Rnd(11 - "aRow#" ) Row Y coordinates for plotting energies. |
aCol Dat | Integer Array | = "aRow Dat" [ "aTo Col Ndx" ] Energy data grouped by column. |
aNP Ndx | Index | = FlatFill(Inflate( "aDat Ndx" by 8) ) Data index corresponding to neighbor position array. (For each position in the energy matrix, there are 8 neighbors.) |
aNP Grps | Mask | = GrpsAltMsk( "aNP Ndx" ) Neighbor position array groups. |
aNP Row# | Integer Array | = FlatFill(Inflate( "aRow#" by 8) ) Neighbor position row #s. |
aNP Col# | Integer Array | = FlatFill(Inflate( "aCol#" by 8) ) Neighbor position column #s. |
aRel NP | Integer Array | = Rnd(Repeat( "aSqSz" ^2, Array( -1, 1, Neg( "aSqSz" - 1) , Neg( "aSqSz" ) , Neg( "aSqSz" + 1) , ( "aSqSz" - 1) , "aSqSz" , ( "aSqSz" + 1) ) ) ) Relative neighbor positions in column data. (Since the form of the dataset is definitive, the positions of the neighbors in the linear dataset is also definitive.) |
aNP0 | Integer Array | = Rnd(FlatFill(Inflate( "aDat Ndx" by 8) ) + "aRel NP" ) Preliminary neighbor positions. |
aIn Range | Mask | = ( "aNP0" > 0) and ( "aNP0" <= "aSqSz" ^2) In-range neighbor position test. |
aTest Top | Mask | = Not( ( "aNP Row#" = 1) and ( ( "aRel NP" = -1) or ( "aRel NP" = ( "aSqSz" - 1) ) or ( "aRel NP" = Neg( "aSqSz" + 1) ) ) ) Top row neighbor position tests. |
aTest Bot | Mask | = Not( ( "aNP Row#" = "aSqSz" ) and ( ( "aRel NP" = 1) or ( "aRel NP" = Neg( "aSqSz" - 1) ) or ( "aRel NP" = ( "aSqSz" + 1) ) ) ) Bottom row neighbor position tests. |
aNP | Integer Array | = Int( "aNP0" `[ "aIn Range" and "aTest Top" and "aTest Bot" ]) Neighbor positions with invalid positions removed.. |
aStart | Integer Array | (Has Formula): "aCol Dat" (Used to initialize object.) Energies at the start of each loop. |
aStart+ | Integer Array | = AtSz( "aMtrx Sz" , Rnd( "aStart" + (GMax( "aStart" ) < 10) ) ) |
aFlash Msk | Mask | = "aStart+" > 9 Marks currently flashing positions. (Positions flashing in current LOOP.) |
aBoost | Integer Array | = AtSz( "aMtrx Sz" , Rnd( "aStart+" + GSum( "aFlash Msk" [ "aNP" ] ||| 8) ) `[Not( "aFlash Msk" ) ]) Boosts energies of active positions by the number of neighbors currently flashing. All positions that have flashed in current STEP are now inactive and have no energy value. |
aInc Step | Scalar | = GMax( "aBoost" & 0) < 10 Indicates when STEP needs to be incremented. (Step increments when all energies are < 10.) |
aEnd | Real Array | = If( "aInc Step" , ( "aBoost" & 0) Else "aBoost" ) Energies at end of loop, to be fed back into Start. If starting a new STEP, energy levels of flashed positions are reset to 0. |
aSym Color | Real Array | = (SkyBlue(0, 0) + (10 * ( "aBoost" - 1) ) ) `[Dat?( "aBoost" ) ] & Yellow(9, 0) Symbol color array for graph. Symbol color intensity and size vary with energy level. |
aTxt Dat | List | = Txt( "aEnd" & 0) Text values for displaying energies in the graph. |
aSym Sz | Real Array | = ( "aEnd" `[ "aEnd" > 0] + 1) /10 Symbol sizes (proportional to energy). Flashing positions display at maximum size. |
aLoop | Scalar | (Has Formula): 0 (Used to initialize) Loop index (continuously incremented by the Compute object to drive the itteration). |
aStep | Scalar | (Has Formula): 0 (Used to initialize.) Current step. |
aFlash Cnt | Scalar | (Has Formula): 0 (Used to initialize.) Total Flash Count. |
aStop | Scalar | = DatCnt( "aBoost" ) = 0 Stop indicator. Set to stop when Boost displays no energies (all positions are flashing). |
aInc Step Cnt | Scalar | = If( "aInc Step" , SetDat(GetProp(Name of "aStep" ) to ( "aStep" + 1) ) ) Increments Step Count. |
aInc Flash Cnt | Scalar | = SetDat(GetProp(Name of "aFlash Cnt" ) to ( "aFlash Cnt" + GSum( "aFlash Msk" ) ) ) Increments Flash Count. |
aBackfeed | String | = If( ( "aLoop" > 0) , SetDatRsz(GetProp(Name of "aStart" ) to "aEnd" ) ) Backfeeds the the data from the end to the start of the loop. Not shown in table. |
aNudge | Index | = Ndx(10000) Iteration index (larger than needed to drive the full iteration). Not shown in table. |
aCompute 11A | Scalar | (Has Formula): Animate( "aLoop" @ "aNudge" by 0 until "aStop" ) Performs the iteration. Not shown in table. |
Day 12A Solution: (Cave Passages)
This solution follows the DQ paradigm of grouped computation.
Starting from the 'Start' node, partial paths are built for all nodes that the 'Start' node is connected to.
In subsequent steps:
The trailing node of each partial path is found and all the partial paths are sufficiently replicated for appending all allowable next nodes.
Each set of replicated paths is appended individually with one of the nodes that the trailing node can connect to.
Completed paths are saved.
Illegal partial paths are discarded.
Remaining partial paths are fed back to 'Start'.
Table 1:
# | Selected Data | A | B | A++B | LC Nodes | Dbl LC Nodes | Both Ways 0 | Both Ways | Sorted Both Ways | All Prev Paths | Start | Step | Path Cnt | Stop |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | start-A | < | A | < | b | bb | <-A | <-A | <-A | <-A-c-A-b-A | 4 | 10 | 1 | |
2 | start-b | < | b | < | c | cc | <-b | <-b | <-b | <-A-> | <-A-c-A-b-d | |||
3 | A-c | A | c | A | d | dd | A-c | A-c | A-> | <-b-> | <-A-b-A-c-A | |||
4 | A-b | A | b | A | A-b | A-b | A-b | <-b-A-> | ||||||
5 | b-d | b | d | b | b-d | b-d | A-c | <-A-b-> | ||||||
6 | A-end | A | > | A | A-> | A-> | b-> | <-A-b-A-> | ||||||
7 | b-end | b | > | b | b-> | b-> | b-A | <-A-c-A-> | ||||||
8 | A | A-< | c-A | b-d | <-b-A-c-A-> | |||||||||
9 | b | b-< | b-A | c-A | <-A-c-A-b-> | |||||||||
10 | c | c-A | d-b | d-b | ||||||||||
11 | b | b-A | ||||||||||||
12 | d | d-b | ||||||||||||
13 | > | >-A | ||||||||||||
14 | > | >-b |
Table 2:
# | Sorted Start | End of Start | Start Grp Szs | Ndx To Next | Next Link 0 | Next Link | Start of Next | End of Next | Next Grp Starts | Next Grp Szs | Infl Start By | Infl Next Ndx | Infl Start | Infl Next | End 0 | Sorted Path Strs | End 01 | Close Msk | End 1 | Closed Paths | Final |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | <-A-c-A-b-A | A | 2 | 3 | A-> | A-> | A | > | 1 | 3 | 3 | 1 | <-A-c-A-b-A | > | <-A-c-A-b-A-> | <>AAAbc | <-A-c-A-b-A-> | 1 | <-A-c-A-b-A-> | <-A-> | |
2 | <-A-b-A-c-A | A | 1 | 4 | A-b | A-b | A | b | 1 | 1 | 3 | 2 | <-A-c-A-b-A | b | <-A-c-A-b-A-b | | <-A-b-A-c-A-> | 1 | <-A-b-A-c-A-> | <-b-> | |
3 | <-A-c-A-b-d | d | 5 | A-c | A-c | A | c | 4 | 1 | 3 | <-A-c-A-b-A | c | <-A-c-A-b-A-c | | <-b-A-> | ||||||
4 | 10 | d-b | d-b | d | b | 1 | <-A-b-A-c-A | > | <-A-b-A-c-A-> | <>AAAbc | <-A-b-> | ||||||||||
5 | 2 | <-A-b-A-c-A | b | <-A-b-A-c-A-b | | <-A-b-A-> | |||||||||||||||
6 | 3 | <-A-b-A-c-A | c | <-A-b-A-c-A-c | | <-A-c-A-> | |||||||||||||||
7 | 4 | <-A-c-A-b-d | b | <-A-c-A-b-d-b | | <-b-A-c-A-> | |||||||||||||||
8 | <-A-c-A-b-> | ||||||||||||||||||||
9 | <-A-c-A-b-A-> | ||||||||||||||||||||
10 | <-A-b-A-c-A-> |
Day 12A Narrative:
# | Object | Type | Explanation |
---|---|---|---|
1 | Selected Data | Dataset selected for computation. | |
2 | aA | List | = ReplStr('end' in ReplStr('start' in TxtBefore('-' in "aSelected Data" ) with '<') with '>') Leading nodes with with 'start' and 'stop' replaced with '<' and '>'. |
3 | aB | List | = ReplStr('end' in ReplStr('start' in TxtAfter('-' in "aSelected Data" ) with '<') with '>') Trailing nodes with with 'start' and 'stop' replaced with '<' and '>'. |
4 | aA++B | List | = "aA" ++ "aB" List of all nodes. |
5 | aLC Nodes | List | = UniqVals(CsSens( "aA++B" [ ( "aA++B" = LwCs( "aA++B" ) ) and ( "aA++B" <> '<') and ( "aA++B" <> '>') ]) ) List of lower case nodes. |
6 | aDbl LC Nodes | List | = "aLC Nodes" + "aLC Nodes" Double lower case nodes. (Used for excluding paths with repeated lower case nodes.) |
7 | aBoth Ways 0 | List | = ( "aA" + '-' + "aB" ) ++ ( "aB" + '-' + "aA" ) Preliminary links expressed both ways |
8 | aBoth Ways | List | "aBoth Ways 0" [ ( "aBoth Ways 0" {1} <> '>') and ( "aBoth Ways 0" { -1} <> '<') ] Valid selection of links expressed both ways. (Links starting with '>' and ending with '<' removed.) |
9 | aSorted Both Ways | List | = Sort( "aBoth Ways" ) Sorted valid links expressed both ways. |
10 | aPrev Paths | List | (Has Formula): List(1) Paths accumulated as of previous step. |
11 | aStart | List | (Has Formula): "aSorted Both Ways" [ "aSorted Both Ways" {1} = '<'] Paths at start of iteration. |
12 | aStep | Scalar | (Has Formula): 0 Iteration step. |
13 | aSorted Start | List | = Sort( "aStart" by "aStart" { -2..End}) Starting paths sorted by ending node, so that thes form groupings. |
14 | aEnd of Start | List | = "aSorted Start" { -2..End} - '-' End node in Start. |
15 | aStart Grp Szs | Integer array | = GrpSzs( "aEnd of Start" ) Group sizes of stargin paths (as sorted by ending nodes). |
16 | aNdx To Next | Index | = StrNdxToAll( "aEnd of Start" in TxtBefore('-' in "aSorted Both Ways" ) ) Index to the next links in the paths. |
17 | aNext Link 0 | List | = "aSorted Both Ways" [ "aNdx To Next" ] All possible next links. |
18 | aNext Link | List | = "aNext Link 0" [Not(StrIn?('<' in "aNext Link 0" ) ) ] Valid next links (links with starting node removed). |
19 | aStart of Next | List | = "aNext Link" {1..2} - '-' Starting node of next link. |
20 | aEnd of Next | List | = "aNext Link" { -2..End} - '-' End node of next link. |
21 | aNext Grp Starts | Index | = FlatFill(Inflate(GrpStrtsNdx( "aStart of Next" ) by "aStart Grp Szs" ) ) Starting indices of the groups in the list of next links. |
22 | aNext Grp Szs | Integer Array | = GrpSzs( "aStart of Next" ) Group sizes in the list of next links. |
23 | aInfl Start By | Integer Array | = RepeatVals( "aNext Grp Szs" by "aStart Grp Szs" ) Group sizes for inflating start. |
24 | aInfl Next Ndx | Index | = NdxFill(Inflate( "aNext Grp Starts" by "aInfl Start By" ) ) Index for inflating next. |
25 | aInfl Start | List | = FlatFill(Inflate( "aSorted Start" by "aInfl Start By" ) ) Inflated Start. |
26 | aInfl Next | List | = "aEnd of Next" [ "aInfl Next Ndx" ] Inflated next. (Note that this is a different method of inflation than used for inflating Start.) |
27 | aEnd 0 | List | = "aInfl Start" + '-' + "aInfl Next" Preliminary End paths. |
28 | aSorted Path Strs | List | = Delimit(Sort(Parse( "aEnd 0" by '-') ||| ParseSzs( "aEnd 0" by '-') ) with '' ||| ParseSzs( "aEnd 0" by '-') ) Path strings with the nodes sorted within the strings. (Used for excluding paths with repeated lower case nodes.) |
29 | aEnd 01 | List | = "aEnd 0" [Not(NdxToMsk(SzOf( "aEnd 0" ) , StrNdxToAll( "aDbl LC Nodes" in "aSorted Path Strs" ) ) ) ] Paths after exlusion of those with repeated LC nodes. |
30 | aClose Msk | Mask | = "aEnd 01" { -1} = '>' Mask to paths closed in this iteration. |
31 | aEnd 1 | List | = "aEnd 01" [Not( "aClose Msk" ) ] Closed paths exluded. |
32 | aClosed Paths | List | = "aEnd 01" [ "aClose Msk" ] Paths closed in this iteration. |
33 | aFinal | List | = Pack( "aAll Prev Paths" ++ "aClosed Paths" ) All accumulated paths. |
34 | aStop | Scalar | = If( ( "aStep" > 0) and (DatSz( "aEnd 1" ) = 0) , 1 Else 0) |
35 | aPath Cnt | Scalar | = If( "aStop" , SzOf( "aFinal" ) Else DatCnt( "aAll Prev Paths" ) ) Path count. |
36 | aNudge | Index | = Ndx(10000) (Not shown in tables.) Iteration index. |
37 | aBackfeed | Scalar | = If( ( "aStep" > 0) , SetDatRsz(GetProp(Name of "aAll Prev Paths" ) to ( "aAll Prev Paths" ++ "aClosed Paths" ) ) + SetDatRsz(GetProp(Name of "aStart" ) to "aEnd 1" ) ) (Not shown in tables.) Feeds the incomplete paths back into 'Start' and records completed paths. |
38 | aCompute | Scalar | = Animate( "aStep" @ "aNudge" by 0 until "aStop" ) (Not shown in tables.) Performs the iteration. |
Day 12A video showing the progress of computation. The computation takes 10 steps. At each step, all paths of the same length are computed and displayed simultaneously. Individual paths are distinguished by color and increasing offsets so that all paths remain visible as the plot proceeds. (The color pattern repeats to accommodate the large number of paths.)
It is best to view the video at 2x speed. (Video is of Part A full dataset.)
Plotting objects: (Data in table is for a very small dataset.)
# | All Nodes | Node Lbls | X | Y0 | Alt Msk | Y | Final | Parsed Paths | Path Szs | Path Grps | Path Codes | Offset | Start End Offsets | Offsets | Xs | Ys | Path Colors |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | < | Start | -1.00 | 0.00 | 0 | 0.00 | <-A-> | < | 3 | 0 | 1 | 5E-5 | 0 | 0 | -1.00 | 0.00 | 1 |
2 | A | A | -0.60 | 0.80 | 1 | 0.80 | <-b-> | A | 3 | 0 | 1 | 5E-5 | -0.60 | 0.80 | 1 | ||
3 | b | b | -0.20 | 0.98 | 0 | -0.98 | <-b-A-> | > | 4 | 0 | 1 | 0 | 0 | 1.00 | 0.00 | 1 | |
4 | c | c | 0.20 | 0.98 | 1 | 0.98 | <-A-b-> | < | 4 | 1 | 2 | 0 | 0 | -1.00 | 0.00 | 2 | |
5 | d | d | 0.60 | 0.80 | 0 | -0.80 | <-A-b-A-> | b | 5 | 1 | 2 | -0.0001 | -0.20 | -0.98 | 2 | ||
6 | > | End | 1.00 | 0.00 | 1 | 0.00 | <-A-c-A-> | > | 5 | 1 | 2 | 0 | 0 | 1.00 | 0.00 | 2 | |
7 | <-b-A-c-A-> | < | 6 | 0 | 3 | 0 | 0 | -1.00 | 0.00 | 3 | |||||||
8 | <-A-c-A-b-> | b | 6 | 0 | 3 | 0.00015 | -0.20 | -0.98 | 3 | ||||||||
9 | <-A-c-A-b-A-> | A | 7 | 0 | 3 | 0.00015 | -0.60 | 0.80 | 3 | ||||||||
10 | <-A-b-A-c-A-> | > | 7 | 0 | 3 | 0 | 0 | 1.00 | 0.00 | 3 | |||||||
11 | < | 1 | 4 | 0 | 0 | -1.00 | 0.00 | 4 | |||||||||
12 | A | 1 | 4 | -0.0002 | -0.60 | 0.80 | 4 | ||||||||||
13 | b | 1 | 4 | -0.0002 | -0.20 | -0.98 | 4 | ||||||||||
14 | > | 1 | 4 | 0 | 0 | 1.00 | 0.00 | 4 |
Plotting narrative:
# | Object | Type | Explanation |
---|---|---|---|
1 | nAll Nodes | List | = '<' ++ Sort(UniqVals( "aA++B" [Not( ( "aA++B" = '<') or ( "aA++B" = '>') ) ]) ) ++ '>' List of all nodes for plotting paths. |
2 | nNode Lbls | List | = 'Start'[ "nAll Nodes" = '<'] & 'End'[ "nAll Nodes" = '>'] & "nAll Nodes" Node labels for the graph. |
3 | nX | Real Array | = Array(SzOf( "nAll Nodes" ) , -1..1) Node label X coordinates. (Spread from -1 to 1.) |
4 | nY0 | Real Array | = Sqrt(1 - "nX" ^2) Preliminary node label Y coordinates. (Computed from the X coordinates to place nodes on a circular arc.) |
5 | nAlt Msk | Mask | = AltMsk(SzOf( "nAll Nodes" ) by 1) Alternating mask for negating alternate Y coordinates. |
6 | nY | Real Array | = ( ( "nY0" `[2.. -2]) `[ "nAlt Msk" ] & (Neg( "nY0" ) `[2.. -2]) `[Not( "nAlt Msk" ) ]) & "nY0" Node label Y coordinates. (Placing nodes in a full circle.) |
7 | aFinal | List | All accumulated paths. (From the path computation.) |
8 | nParsed Paths | List | = Parse( "aFinal" by '-') All accumulated paths parsed sequentially into individual nodes for plotting. |
9 | nPath Szs | Integer Array | = ParseSzs( "aFinal" by '-') The number of nodes in each sequentially parsed path. |
10 | nPath Grps | Mask | = AltMsk( "nPath Szs" ) Groupings indicating separate paths in the parsed list. |
11 | nPath Codes | Integer Array | = GrpCds( "nPath Grps" ) Sequential path codes. (Used to provide offsets for plotting paths, and for assigning colors to paths.) |
12 | nOffset | Scalar | Sequential path offset for plotting paths. (Successive paths are assigned increasing offsets alternating positive and negative so that all paths stay visible.) |
13 | nStart End Offsets | Real Array | = 0[ ( "nParsed Paths" = '<') or ( "nParsed Paths" = '>') ] Zero offsets for Start and End nodes |
14 | nOffsets | Real Array | = "nStart End Offsets" & ( "nPath Codes" * ( ( -1`[ "nPath Grps" ]) & 1) ) * "nOffset" Offsets to separate paths for plotting. |
15 | nXs | Real Array | = Code( "nAll Nodes" in "nParsed Paths" with "nX" ) + "nOffsets" X coordinates of nodes in parsed paths. (Successively offset so all prfeviously plotted paths remain visible.) |
16 | nYs | Real Array | = Code( "nAll Nodes" in "nParsed Paths" with "nY" ) + "nOffsets" Y coordinates of nodes in parsed paths. (Successively offset so all prfeviously plotted paths remain visible.) |
17 | nPath Colors | Real Array | = FlatFill(Inflate( (Repeat(3, Array(1399, 1..1399) ) ) by "nPath Szs" ) ) Colors for plotting paths. (DQ uses a limited set of colors for object, table and graph elements, most of which can be set globally or microscopically, and dynamically. The colors can be accessed numerically in a range of 0 to 1399, in which the 100s place indicates color, the 10s place indicates intensity, and the 1s place indicates gray shade.) |
Day 12B Narrative:
The solution for Part B differs from Part A as follows: Following "End0":
(Solution table not shown.)
# | Object | Type | Explanation |
---|---|---|---|
1 | End001 | List | = Parse( "aEnd 0" by '-') Parsed preliminary end paths. |
2 | Grps001 | Integer Array | = ParseSzs( "aEnd 0" by '-') Groupings in parsed paths. |
3 | LC Node Freq | Integer Array | = CsSens(Freq( "aLC Nodes" in "mEnd001" ||| "mGrps001" ) ) Frequency of the lower case nodes in the preliminary end paths. |
4 | Test | Mask | = (GSum( ( "mLC Node Freq" = 2) ||| SzOf( "aLC Nodes" ) ) < 2) and (GMax( "mLC Node Freq" ||| SzOf( "aLC Nodes" ) ) < 3) Mask for retaining only legal paths. (Paths in which there are less than 2 lower case node frequencies = 2, and in which no lower case nodes frequencies exceed 2.) |
5 | End01 | List | = "aEnd 0" [ "mTest" ] Paths after exlusion of illegals. |
Day 13 Solution:
# | Selected Data | Dat Msk | Coords | X | Y | Folds | MaxY | MaxX | Full Y | Full X | Ndx To Dots | Dot Msk | Start Y | Start X | Start Dots | Step | Go | XMax | Nudge | Instr | Fold Dir | Fold Pos | Static Ndx | Folding Ndx | End Y | End X | End Dots | Plot Dots | Num Dots |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 6,10 | 1 | 6,10 | 6 | 10 | y=7 | 14 | 10 | 0 | 0 | 117 | 0 | 0 | 0 | 1 | 2 | 1 | 10 | 1 | x=5 | 0 | 5 | 1 | 11 | 0 | 0 | 1 | 0 | 16 |
2 | 0,14 | 1 | 0,14 | 0 | 14 | x=5 | 0 | 1 | 155 | 0 | 0 | 1 | 0 | 2 | 2 | 10 | 0 | 1 | 1 | 0 | |||||||||
3 | 9,10 | 1 | 9,10 | 9 | 10 | 0 | 2 | 120 | 0 | 0 | 2 | 1 | 3 | 9 | 0 | 2 | 1 | 0 | |||||||||||
4 | 0,3 | 1 | 0,3 | 0 | 3 | 0 | 3 | 34 | 1 | 0 | 3 | 1 | 4 | 8 | 0 | 3 | 1 | 0 | |||||||||||
5 | 10,4 | 1 | 10,4 | 10 | 4 | 0 | 4 | 55 | 0 | 0 | 4 | 0 | 5 | 7 | 0 | 4 | 1 | 0 | |||||||||||
6 | 4,11 | 1 | 4,11 | 4 | 11 | 0 | 5 | 126 | 0 | 0 | 5 | 0 | 12 | 22 | 1 | 0 | 1 | -1 | |||||||||||
7 | 6,0 | 1 | 6,0 | 6 | 0 | 0 | 6 | 7 | 1 | 0 | 6 | 1 | 13 | 21 | 1 | 1 | 0 | ||||||||||||
8 | 6,12 | 1 | 6,12 | 6 | 12 | 0 | 7 | 139 | 0 | 0 | 7 | 0 | 14 | 20 | 1 | 2 | 0 | ||||||||||||
9 | 4,1 | 1 | 4,1 | 4 | 1 | 0 | 8 | 16 | 0 | 0 | 8 | 0 | 15 | 19 | 1 | 3 | 0 | ||||||||||||
10 | 0,13 | 1 | 0,13 | 0 | 13 | 0 | 9 | 144 | 1 | 0 | 9 | 1 | 16 | 18 | 1 | 4 | 1 | -1 | |||||||||||
11 | 10,12 | 1 | 10,12 | 10 | 12 | 0 | 10 | 143 | 0 | 0 | 10 | 0 | 23 | 33 | 2 | 0 | 1 | -2 | |||||||||||
12 | 3,4 | 1 | 3,4 | 3 | 4 | 1 | 0 | 48 | 0 | 1 | 0 | 1 | 24 | 32 | 2 | 1 | 0 | ||||||||||||
13 | 3,0 | 1 | 3,0 | 3 | 0 | 1 | 1 | 4 | 0 | 1 | 1 | 0 | 25 | 31 | 2 | 2 | 0 | ||||||||||||
14 | 8,4 | 1 | 8,4 | 8 | 4 | 1 | 2 | 53 | 0 | 1 | 2 | 0 | 26 | 30 | 2 | 3 | 0 | ||||||||||||
15 | 1,10 | 1 | 1,10 | 1 | 10 | 1 | 3 | 112 | 0 | 1 | 3 | 0 | 27 | 29 | 2 | 4 | 1 | -2 | |||||||||||
16 | 2,14 | 1 | 2,14 | 2 | 14 | 1 | 4 | 157 | 1 | 1 | 4 | 1 | 34 | 44 | 3 | 0 | 1 | -3 | |||||||||||
17 | 8,10 | 1 | 8,10 | 8 | 10 | 1 | 5 | 119 | 0 | 1 | 5 | 0 | 35 | 43 | 3 | 1 | 0 | ||||||||||||
18 | 9,0 | 1 | 9,0 | 9 | 0 | 1 | 6 | 10 | 0 | 1 | 6 | 0 | 36 | 42 | 3 | 2 | 0 | ||||||||||||
19 | 0 | 1 | 7 | 0 | 1 | 7 | 0 | 37 | 41 | 3 | 3 | 0 | |||||||||||||||||
20 | fold along y=7 | 0 | 1 | 8 | 0 | 1 | 8 | 0 | 38 | 40 | 3 | 4 | 1 | -3 | |||||||||||||||
21 | fold along x=5 | 0 | 1 | 9 | 0 | 1 | 9 | 0 | 45 | 55 | 4 | 0 | 1 | -4 | |||||||||||||||
22 | 1 | 10 | 0 | 1 | 10 | 0 | 46 | 54 | 4 | 1 | 1 | -4 | |||||||||||||||||
23 | 2 | 0 | 0 | 2 | 0 | 0 | 47 | 53 | 4 | 2 | 1 | -4 | |||||||||||||||||
24 | 2 | 1 | 0 | 2 | 1 | 0 | 48 | 52 | 4 | 3 | 1 | -4 | |||||||||||||||||
25 | 2 | 2 | 0 | 2 | 2 | 0 | 49 | 51 | 4 | 4 | 1 | -4 | |||||||||||||||||
26 | 2 | 3 | 0 | 2 | 3 | 0 | 56 | 66 | 5 | 0 | 0 | ||||||||||||||||||
27 | 2 | 4 | 0 | 2 | 4 | 0 | 57 | 65 | 5 | 1 | 0 | ||||||||||||||||||
28 | 2 | 5 | 0 | 2 | 5 | 0 | 58 | 64 | 5 | 2 | 0 | ||||||||||||||||||
29 | 2 | 6 | 0 | 2 | 6 | 1 | 59 | 63 | 5 | 3 | 0 | ||||||||||||||||||
30 | 2 | 7 | 0 | 2 | 7 | 0 | 60 | 62 | 5 | 4 | 0 | ||||||||||||||||||
31 | 2 | 8 | 0 | 2 | 8 | 0 | 67 | 77 | 6 | 0 | 0 | ||||||||||||||||||
32 | 2 | 9 | 0 | 2 | 9 | 0 | 68 | 76 | 6 | 1 | 0 | ||||||||||||||||||
33 | 2 | 10 | 0 | 2 | 10 | 1 | 69 | 75 | 6 | 2 | 0 | ||||||||||||||||||
34 | 3 | 0 | 1 | 3 | 0 | 1 | 70 | 74 | 6 | 3 | 0 | ||||||||||||||||||
35 | 3 | 1 | 0 | 3 | 1 | 0 | 71 | 73 | 6 | 4 | 0 |
Day 13 Narrative:
# | Object | Type | Explanation |
---|---|---|---|
1 | Selected Data | List | Dataset selected for computation. |
2 | aDat Msk | Mask | = Int?(Num( "aSelected Data" {1}) ) Mask to the dot data. (Used to separate the dot data from the instructions.) |
3 | aCoords | List | = "aSelected Data" [ "aDat Msk" ] Dot coordinate pairs (X,Y). |
4 | aX | Real Array | = Extract#( "aCoords" ) X coordinates of dots. |
5 | aY | Real Array | = Extract#(2, "aCoords" ) Y coordinates of dots. |
6 | aFolds | List | = TxtAfter('g ' in Pack( "aSelected Data" [Not( "aDat Msk" ) ]) ) Fold instructions. |
7 | aMaxY | Scalar | = GMax( "aY" ) Maximum Y coordinate. (Defines the Y extent of the full point array.) |
8 | aMaxX | Scalar | = GMax( "aX" ) Maximum X coordinate. (Defines the X extent of the full point array.) |
9 | aFull Y | Index | = FlatFill(Inflate(Ndx(0.. "aMaxY" by 1) by ( "aMaxX" + 1) ) ) Y coordinates of all the positions in the point array. Since the point array coordinates are zero based, the size of the point array is the product of MaxX+1 and MaxY+1. Starts with an index ranging from 0 to the maximum Y coordinate, inflates this by the range of X coordinates, and fills in the empty space. |
10 | aFull X | Index | = Repeat( ( "aMaxY" + 1) , Ndx(0.. "aMaxX" by 1) ) X coordinates of all the positions in the point array. Creates an index ranging from 0 to the maximum X coordinate and repeats this by the range of Y coordinates. |
11 | aNdx To Dots | Real Array | = "aY" * ( "aMaxX" + 1) + ( "aX" + 1) Indices of all the dots in the original point array. Since the 2 dimmensional point array is expressed linearly in Y coordinate precedence, to obtain the index of each dot coordinate pair, the Y coordinate is multiplied by MaxX+1 and then further offset by the X coordinate + 1. |
12 | aDot Msk | Mask | = NdxToMsk(SzOf( "aFull X" ) , "aNdx To Dots" ) Mask to all the dots in the original point array. (Obtained from the indices of the dots.) |
13 | aStart Y | Integer Array | (Has Formula): "aFull Y" (Used for initialization.) Y coordinates of all the POSITIONS in the point array at the start of each iteration. |
14 | aStart X | Integer Array | (Has Formula): "aFull X" (Used for initialization.) X coordinates of ALL the POSITIONS in the point array at the start of each iteration. |
15 | aStart Dots | Mask | (Has Formula): "aDot Msk" (Used for initialization.) Mask to all the DOTS in the point array at the start of each iteration. |
16 | aStep | Scalar | (Has Formula): 0 (Used for initialization.) Current iteration step. |
17 | aGo | Scalar | = "aStep" > 0 Compute indicator. |
18 | aXMax | Scalar | = GMax( "aStart X" [1.. ( "aMaxX" + 1) ]) Maximum X position in the current point array. |
19 | aNudge | Index | = NdxTo( "aFolds" ) Iteration index. (Used to step through the iteration.) |
20 | aInstr | String | = If( "aGo" , "aFolds" [ "aStep" ] Else ' ') Current fold instruction. |
21 | aFold Dir | Scalar | = "aInstr" {1} = 'y' Direction of fold. 0=Left and 1=Up (The direction of fold is expressed as an integer so that it can be used directly as a boolean.) (The formula returns 1 if the first character of the instruction is 'y'.) |
22 | aFold Pos | Scalar | = Extract#( "aInstr" ) & 0 Position of fold line. (The formula extracts the numeric portion of the instruction, but substitlutes 0 if there is no instruction, as in prior to computation.) |
23 | aStatic Ndx | Index | = If( "aFold Dir" , MskToNdx( "aStart Y" < "aFold Pos" ) Else MskToNdx( "aStart X" < "aFold Pos" ) ) Index for retaining the static part of point array on folding. For an 'Up' fold, this retains the coordinates with Y less than the Y coordinate at the fold. For a 'Left' fold, this retains the coordinates with X less than the X coordinate at the fold. |
24 | aFolding Ndx | Index | = If( "aFold Dir" , Rev(Rev(MskToNdx( "aStart Y" > "aFold Pos" ) ) ||| ( "aXMax" + 1) ) Else Rev(MskToNdx( "aStart X" > "aFold Pos" ) ||| ( "aXMax" - "aFold Pos" ) ) ) Index for extracting and arranging the folding part of point array. For the 'Up' fold, this extracts the bottom part of the array, reverses it to execute the fold, then applies another reverse to the groups of X coordinates to restore their original order. For the 'Left' fold, this extracts the bottom section of each group of X coordinates and reverses them within their groups. |
25 | aEnd Y | Integer Array | = If( "aGo" , "aStart Y" [ "aStatic Ndx" ] Else "aStart Y" ) Y coordinates of all the positions in the point array after fold. |
26 | aEnd X | Integer Array | = If( "aGo" , "aStart X" [ "aStatic Ndx" ] Else "aStart X" ) X coordinates of all the positions in the point array after fold. |
27 | aEnd Dots | Mask | = If( "aGo" , ( "aStart Dots" [ "aStatic Ndx" ] or "aStart Dots" [ "aFolding Ndx" ]) Else "aStart Dots" ) Mask to all the dots in the point array after folding. (Uses the Static and Folding indexes to separately extract and arrange those portions of the Dot mask, and then combines the two reslulting masks with OR.) |
28 | aPlot Dots | Integer Array | = Neg( "aEnd Y" `[ "aEnd Dots" > 0]) Y coordinates of dots after folding, extracted in place so that they still correspond to the X coordinates in the full X array. (This is the array that gets plotted on the graph against the full X array.) (Note that the negative of the Y coordinates are used so that the dots are plotted below the X axis, with 0,0 in the upper left. If the positive values were used, the plot would be upside down.) |
29 | aNum Dots | Scalar | = GSum( "aEnd Dots" > 0) Number of dots remaining after folding. |
30 | aBackfeed | Scalar | = If( "aGo" , (SetDatRsz(GetProp(Name of "aStart Y" ) to "aEnd Y" ) + SetDatRsz(GetProp(Name of "aStart X" ) to "aEnd X" ) + SetDatRsz(GetProp(Name of "aStart Dots" ) to "aEnd Dots" ) ) ) Not in table. Feeds the coordinate arrays and dot mask from the end of one iteration to the beginning of the next. |
31 | aCompute | Scalar | = Animate( "aStep" @ "aNudge" by 0) Not in table. Performs the iteration. |