Advent of Code is back! Unwrap daily challenges to sharpen your Alteryx skills and earn badges along the way! Learn more now.
Free Trial

General Discussions

Discuss any topics that are not product-specific here.

Advent of Code 2020 - BaseA Style (Day 22)

Jean-Balteryx
16 - Nebula
16 - Nebula

Discussion thread for day 22 of the Advent of Code : https://adventofcode.com/2020/day/22

7 REPLIES 7
danilang
19 - Altair
19 - Altair

Back to the familiar, if somewhat finicky, realm of substring parsing to play a macro free game for part I.  Like the answer to the question of Life, the Universe and Everything, part II will require Deep Thought. 

 

Spoiler
Part I
w.png
Part II requires a generic recursive algorithm that would be fairly easy in a traditional programming language, but is complex(for me at least) to implement in Alteryx.  I have a inkling of how I could accomplish it, involving keeping track of parents and recursion level, but I won't be able to flush it out completely today 

Dan

Greg_Murray
12 - Quasar

Here is my solution for part 1. I took the iterative approach. 

Spoiler
workflow 
Greg_Murray_0-1608647459706.png

iterative Macro

Greg_Murray_1-1608647527186.png

 

dsmdavid
11 - Bolide

I toyed with the idea of replacing the macro for a combination of tools for the first part, but thought "let's wait for part 2"...

 

Spoiler

Part II rules are surprisingly simple, provided you read them well (including:
...(the quantity of cards copied is equal to the number on the card they drew to trigger the sub-game)...
and
..(again so that the winner's card is above the other card)...
)
I missed them for a while and spent a long time trying to understand why the macro was not working...


Part II now works with the "sample" dataset. But 100 000 iterations later it has not reached the end for the real input, which makes me think there may be something wrong with the macro, or, it's going to take a looong while to get it there.

Alteryx_Day_22_a.png

The input is converted into:
Alteryx_Day_22_b.png
Deeper levels of recursion are kept as additional rows:
Alteryx_Day_22_c.png
It's awfully inefficient and the workflow is utterly cluttered right now. But not sure how much gain would be obtained from cleaning it properly.
Alternatively, it may be worth rethinking the strategy altogether 😅

Sample data:
Spoiler
Alteryx_Day_22_d.png

 

 

cgoodman3
14 - Magnetar
14 - Magnetar

Took a bit longer than I would have liked to solve part 1 with first an error of mixing numbers and strings so not getting the desired output in the example dataset, and then when running the full dataset being out by one which was just to do with how I dealt the last cards in the pack, but managed to fix it.

 

It's nice being back into it as I just didn't really have the time last week to participate.

Spoiler
cgoodman3_0-1608655943146.png

Macro

cgoodman3_1-1608656081065.png

 

Chris
Check out my collaboration with fellow ACE Joshua Burkhow at AlterTricks.com
jdunkerley79
ACE Emeritus
ACE Emeritus

Ok, so Part 2 is horrific... but done in BaseA

 

 

Spoiler
jdunkerley79_0-1608659790741.png


My approach for Part 2 is to turn the recursion into iteration and use generate rows.
- I encode the 1-50 as ASCII characters (value plus 48 so 1=1, 2=2,...9=9,10=:,...)
- First 2 words of the string are state if player 1 and 2 in the current game (or subgame)
- After word 2, the previous state of the current game is stored as (P1#P2) separated by spaces
- This is checked to see if P1 wins the game, if so the current game is ended and the change made to parent game (or iteration terminates) and current game is removed (replace up to first ` ! `)
- Otherwise, if need to recurse then a new pair of P1 and P2 are added followed by a ` ! ` which marks the end of the current game state
- If someone wins a game as other player runs out, then as above with P1 happens
- If someone wins a round then the state is added to list and word 1 and word 2 are manipulated to be the new value

The horrific formula is below:

IF REGEX_CountMatches(C," ") = 0 THEN
   "*"
ELSEIF Contains(REGEX_Replace(C, " ! .*$", ""),GetWord(C,0) + "#" + GetWord(C,1)) THEN
    // Player 1 win by termination
    iif(Contains(C," ! "),
        Substring(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0), 1)
        + Left(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0), 1)
        + Left(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1), 1)
        + " " + Substring(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1), 1)
        + " " + GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0) + "#" + GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1)
        + Regex_Replace(C, "^[^!]+ ! [^ ]+ [^ ]+ ?", " "),
        Substring(GetWord(C,0),1) + Left(GetWord(C,0),1) + Left(GetWord(C,1),1))
ELSEIF CharToInt(GetWord(C,0)) - 48 < Length(GetWord(C,0)) and CharToInt(GetWord(C,1))-48 < Length(GetWord(C,1)) THEN
    // Do I need to recurse
    Substring(GetWord(C,0),1,CharToInt(GetWord(C,0)) - 48) + " " + Substring(GetWord(C,1),1,CharToInt(GetWord(C,1))-48) + " ! "+ C
ELSEIF CharToInt(GetWord(C,0)) > CharToInt(GetWord(C,1)) AND Length(GetWord(C,1)) = 1 THEN 
    // Player 1 win
    iif(Contains(C," ! "),
        Substring(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0), 1)
        + Left(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0), 1)
        + Left(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1), 1)
        + " " + Substring(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1), 1)
        + " " + GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0) + "#" + GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1)
        + Regex_Replace(C, "^[^!]+ ! [^ ]+ [^ ]+ ?", " "),
        Substring(GetWord(C,0),1) + Left(GetWord(C,0),1) + Left(GetWord(C,1),1))
ELSEIF CharToInt(GetWord(C,0)) < CharToInt(GetWord(C,1)) AND Length(GetWord(C,0)) = 1 THEN 
    // Player 2 win
    iif(Contains(C," ! "),
        Substring(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0), 1)
        + " " + Substring(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1), 1)
        + Left(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1), 1)
        + Left(GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0), 1)
        + " " + GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 0) + "#" + GetWord(REGEX_Replace(C, "^[^!]+ ! ", ""), 1)
        + Regex_Replace(C, "^[^!]+ ! [^ ]+ [^ ]+ ?", " "),
        Substring(GetWord(C,1),1) + Left(GetWord(C,1),1) + Left(GetWord(C,0),1))
ELSE
    // Play a turn
    iif(CharToInt(GetWord(C,0))>CharToInt(GetWord(C,1)),
        Substring(GetWord(C,0),1) + Left(GetWord(C,0),1) + Left(GetWord(C,1),1) + " " +Substring(GetWord(C,1),1),
        Substring(GetWord(C,0),1) + " " +Substring(GetWord(C,1),1)+ Left(GetWord(C,1),1) + Left(GetWord(C,0),1))

    // Add New Played
    + " " + GetWord(C,0) + "#" + GetWord(C,1) 

    // Keep Old
    + Regex_Replace(C,"^[^ ]+ [^ ]+ ?", " ")
ENDIF

 
Just about 1 mm iterations in about an hour

 

 

AkimasaKajitani
17 - Castor
17 - Castor

Day22!

 

I cleared Part 1 only.

Spoiler
AkimasaKajitani_0-1608731704788.png


Iterative Macro

AkimasaKajitani_1-1608731722467.png

 

 

AS anonymous user #1105310

https://github.com/AkimasaKajitani/AdventOfCode

 

 

dsmdavid
11 - Bolide

Doing some cleaning up I realized I didn't post my final approach. It did take a looong time

Alteryx_Day_22_e.png

While I was building the iterative macro, I thought that a lot of the steps were just moving data from one place to another and it was all just a big "if else" statement. @jdunkerley79 's generate rows proves that was right, but I was not able to come up with a solution like that. Quite impressive.

Spoiler
main workflowmain workflowiterativeiterative
Labels
Top Solution Authors