Advent Challenge 2: The Present Vault Raid!

9

<< Prev Next >>

Challenge

Now that Santa has finally figured out how to get into his present vault, he realises that somehow the elves got in there before him and stole some of his presents! They haven't figured out how to leave the vault yet though, so Santa has to try and catch them all. Santa and the elves both have infinite energy to run around but unfortunately the elves have a higher infinity of energy, so if they end up running in loops everywhere, the elves have gotten free.

Given a graph of n nodes and e edges with a walk existing between any two nodes, and the positions of the elves and Santa, determine how many elves Santa can catch before he gets tired.

The chase is turn-based. Each cycle, the elves first all move simultaneously (they can move through each other and onto the same node as well), and then Santa will move. If Santa moves onto the same node as an elf, then he has caught that elf. Each elf may only move from one node to its neighbour in one step. The same goes for Santa in the beginning, but for every elf he has caught, Santa can take one extra step. So, if Santa has caught an elf, then he can move from a node to its neighbour's neighbour. This means he could move to a node and then back. However, since Santa is running too quickly during this time period, he will not catch any elves that passes in the intermediate steps (so if he is on A, A is connected to B, B is connected to C, there is an elf on B, and Santa moves from A -> B -> C, the elf has not yet been caught). However, Santa doesn't have to move that many steps at once; he moves up to 1 + (number of elves caught) each turn.

Note that all of the elves must move each turn, and if an elf moves onto Santa's node, they get caught.

All entities (elves, Santa) will be on distinct nodes in the beginning.

Specifications and Rules

Your program should theoretically work for input of any size. The input will be given as a graph, the positions of the elves, and the position of Santa. You may take the graph in any reasonable format (list of nodes + list of edges, list of edges, adjacency matrix, cycle notation, etc), and you may take the positions in any reasonable format that works with your graph input format (index in the list of nodes, etc). The output should be a single positive integer indicating the maximum number of elves that Santa can catch.

Test Cases

These are given as lists of edges and node numbers for positions.

Input -> Output
[(0, 1), (1, 2)], [0, 2], 1 -> 2 # Easy win for Santa, the elves get themselves caught :P
[(0, 1), (1, 2), (2, 3), (3, 0)], [0, 1], 2 -> 2 # The elf opposite of Santa cannot escape but the other one can always just run away each turn, until Santa catches the first elf. Then he can easily just catch the rest.
[(0, 1), (1, 2), (2, 3), (3, 0)], [1], 0 -> 0 # Santa will never catch up
[(0, 1), (1, 2), (2, 3), (3, 0), (1, 4), (4, 5), ..., (10, 11), (11, 3)], [2, 6], 0 -> 2 # The first elf moves to either 1 or 3 and then gets caught. Then, Santa can use his 2-step move to catch up to the second elf no matter what.

I think Santa can catch either no elves or all the elves, so this challenge might just be "can he catch an elf" hint hint

Rules

  • Standard Loopholes Apply
  • This is a challenge, so the shortest answer in bytes wins
  • No answers will be accepted

Happy Golfing!

Note: I drew inspiration for this challenge series from Advent Of Code. I have no affiliation with this site

You can see a list of all challenges in the series by looking at the 'Linked' section of the first challenge here.

HyperNeutrino

Posted 2017-12-02T20:39:20.700

Reputation: 26 575

1I wish I knew Santa's elves were that wicked before... – Mr. Xcoder – 2017-12-02T20:45:04.253

The approach to solve this would probably be: 1 Prove some mathematical statements. 2 Post a Jelly (/...) answer in less than 10 bytes. – user202729 – 2017-12-03T11:09:03.020

Well, it is possible that Santa can catch some but not all elves (is it possible that some elves starts at the Santa's position; and is it possible that the elves voluntarily let Santa catch them?) – user202729 – 2017-12-03T12:39:42.443

Edit: No for the first question, but probably for the second question. – user202729 – 2017-12-03T13:13:10.703

@user202729 No, all entities start at different locations. For the second question, yes; if an elf moves onto Santa's node, then it is considered caught. Also, as soon as Santa catches an elf, then to catch any remaining elf, draw a path from Santa to the elf (which must exist), and then move along it; whenever the elf moves, add its movement to the end of the path. Santa will catch up because he has step size larger than the elf. – HyperNeutrino – 2017-12-03T16:01:30.977

So the elves may sacrifice themselves to make the challenge harder. For example: Graph 0-1, 1-2, 2-3, 3-0 (cyclic 4, bipartite) with Santa step size = 3 (because of two self-sacrifice elves) and the other elf escape - in that case, Santa can catch 2 out of 3 elves. – user202729 – 2017-12-03T16:11:42.600

3@user202729 Note that Santa doesn't have to move 3 spaces; he can move anywhere from 1 to 3 spaces. That might be the source of confusion here. – HyperNeutrino – 2017-12-03T17:15:28.940

Tool to generate adjacency list from edge list, because I'm going to post an answer that take adjacency list as input: Try it online!

– user202729 – 2017-12-05T11:25:34.877

Answers

1

Wolfram Language (Mathematica), 129 bytes

Block[{a=#},Clear@f;s_~f~e_:=If[s==e,1,s~f~e=0;s~f~e=Min[(hMax[#~f~h&/@a@s,Boole[h==s]])/@a@e]];Tr[Max[(e#3~f~e)/@#2]^#2]]&

Try it online!

Similar approach to my answer to this question.

The function takes 3 arguments as input: adjacency list represented as an association (tool to generate adjacency list from edge list), elves position and santa position.

Note that Clear[f] is necessary, because function submissions must be reusable.

The code below is ungolfed code with partial explanation. More explanation later.

reverseBoole = # != 0 &

(* Or@@{a, b} === reverseBoole[booleOr[Boole[{a, b}]]] *)
booleOr = Max

booleAnd = Min

(* Boole@f[s, e] = Santa can catch Elf ? *)

mainfunc = Block[{adjlist = #},
  Clear[f];
  f[s_, e_] := If[ s == e, f[s, e] = 1,
    f[s, e] = Boole[False];
    f[s, e] = booleAnd[
      (e1  booleOr[
        ( s1  f[s1, e1] ) /@ adjlist[s],
        Boole[e1 == s]
      ]) /@ adjlist[e]
    ]
  ];
  If [ 0 == booleOr[ ( e  f[#3, e] ) /@ #2 ] , 0, Length[#2] ]
]&

user202729

Posted 2017-12-02T20:39:20.700

Reputation: 14 620