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)

Day 1
# 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:

Day1 Explanation
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)

Day 2
# 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:

Day2 Explanation
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.)

Day 3 A (Alternate Method)
# 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:

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.

Day 3B (O2 Gen) Solution
# 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:

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.

Day 3B (CO2 Scrub) Solution
# 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)

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:

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.

Day 4B Solution (Bingo)
# 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:

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.)

Day 5 Solutions (Hydrothermal Vents)
# 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:

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.

Day 6 Solution 1 (Lanternfish)
# 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:

Day 6-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.

Day 6 Solution 2
# 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:

Day 6-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.

Day 6-3 Solution 3
## 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:

Day 6-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.

Day 7 Solution 1 (Global Computation)
# 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:

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.

Day 7 Solution 2
# 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:

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)

Day 8 Table 1
# 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)

Day 8 Table 2
# 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:

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.

Day 9 A Solution
# 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:

Day 9 A 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.

Day 9 B Solution
# 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:

Day 9 B 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.

Day 10A Solution (Syntax Scoring)
# 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:

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.

Day 10B Solution
# 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:

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.

Day11 Solution
# 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:

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:

Day 12A Solution 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:

Day 12A Solution 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:

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.)

Day 12A Plotting
# 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:

Day 12A 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.)

Day 12B Narrative
# 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:

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:

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.
Create your website for free! This website was made with Webnode. Create your own for free today! Get started