After a bit of a hiatus for Christmas and family, I’m going to try to finish off the last couple problems before I have to go back to work on January 4th. Well at least the first part of each…

Part 1

I’ll start with the naive solution, which should suffice to get us through 100 moves. First parse the string into an array of Ints:

    ns = [parse(Int,x) for x in ins]

Each round I’ll construct the next ns such that the current cup is the first element in the list, this should simplify finding the destination cup, since I’ll just have to check elements [5:end] ([1] is current, [2:4] are picked up), which I’ll refer to as the remaining cups. So to decide which cup is the destination I get the maximum of all remaining cups that are less than the current, and if there are none then get the maximum of all remaining cups:

        ds = filter(x->x<ns[1], @view ns[5:end])
        d = isempty(ds) ? maximum(@view ns[5:end]) : maximum(ds)

I then find the index of the destination (probably room for improvement here: I never actually need the value of the destination cup), and construct the new cup array from four parts:

  1. The remaining cups up to and including the destination cup.
  2. The picked up cups.
  3. The remaining cup after the destination cup.
  4. The current cup.
        id = findfirst(x->x==d, ns)
        ns = [ns[5:id]; ns[2:4]; ns[id+1:end]; ns[1]]

After all the rounds I just need to re-assemble the list starting from after the one cup and join it into a string:

    i1 = findfirst(x->x==1, ns)
    join([ns[i1+1:end];ns[1:i1-1]])

Part 2

to be continued…