12
\$\begingroup\$

Consider binary strings (reading from left to right) starting with a '1' as ponds of lily pads. A '1' signifies a frog sitting on the lily pad, and a '0' represents an empty lily pad.

Here, we see a pond with 7 lily pads on which 4 frogs are sitting:

1101001

The frogs want to all party together. This means that, ultimately, they all want to sit on a single lily pad. However, there are rules as to how to achieve this:

  • All of the frogs on a single lily pad jump at once.
  • If there are k frogs jumping they jump k spaces to the right or left. (they must all jump in the same direction.)
  • Frogs are not allowed to jump onto an empty lily pad.

Examples

1
11       -> 02
111      -> 021      -> 030
1011     -> 1020     -> 3000 
1101001  -> 0201001  -> 0003001  -> 0000004 
10001111 -> 10002011 -> 10002020 -> 10004000 -> 50000000
10110111 -> 10020111 -> 10000311 -> 10000302 -> 10000500 -> 60000000

Challenge

Given n, show all ponds as binary strings, which allow the n frogs to gather to a party. But disregard ponds, which are only a left-right reversal of another one. The output can be given as a comma-separated list or line by line.

For example, for 4 frogs, the output is

[1111, 11101, 11011, 111001, 1101001]

These sequences of jumps lead to the party:

1111 -> 0211 -> 0013 -> 0004
11101 -> 02101 -> 03001 -> 00004
11011 -> 02011 -> 02020 -> 04000
111001 -> 201001 -> 003001 -> 000004
1101001 -> 0201001 -> 0003001 -> 0000004

As a test case show the 12 solutions for 5 frogs. The order is not fixed!

11111      
111011     
111101     
1101011    
1110011    
1111001    
11010011   
11011001   
11110001   
111010001  
1110010001 
11010010001

This is , so each language's shortest code in bytes wins.

Credits

Gordon Hamilton, Jumping Frogs

Gordon Hamilton and Brady Haran, Frog Jumping, Numberphile video.

Glen Whitney, OEIS A378004 (counting the number of solutions).

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Do the k frogs jumping together all have to be on the same lily pad? For example 1011011001 -> 1002002001 -> 1002011001 -> 0002002002 -> 0000003003 -> 0000000006? I don't think it makes a difference for the case where n=4, and none of the example show frogs from different lily pads jumping simultaneously. \$\endgroup\$
    – Wheat Wizard
    Commented Nov 26 at 15:03
  • \$\begingroup\$ Q: "Do the k frogs jumping together all have to be on the same lily pad? " A: Yes. \$\endgroup\$ Commented Nov 26 at 15:43
  • 1
    \$\begingroup\$ Then my follow up question is: Must all frogs on the same lily pad jump at once? For example is 50310001 -> 30510001 -> 30010006 -> 00040006 -> 0000000X permitted? The question should really state this, because as worded now it entails that both of these are permissible moves. \$\endgroup\$
    – Wheat Wizard
    Commented Nov 26 at 15:54
  • \$\begingroup\$ Noting that they have to jump from the same pad also obviates the question I was going to ask about if it's permissible for one frog to jump onto a pad with all of the frogs currently on that pad jumping off it at the same time... "Together" is really not that unambiguous! Is it also the case that they must all jump in the same direction? On another note, are answers strictly required to eliminate duplicates under reflection, or are they merely permitted to? (You should really provide more actual test cases, instead of asking solvers to do so...) \$\endgroup\$ Commented Nov 26 at 16:20
  • 1
    \$\begingroup\$ (I believe a simpler case that requires partial jumps would be 1110101 -> 0210101 -> 0300101 -> 0000401 -> 0000203 -> 0000005? All the more reason that you should really give n=5 as a real test case if you want it as a "test case"...) \$\endgroup\$ Commented Nov 26 at 17:06

6 Answers 6

6
\$\begingroup\$

JavaScript (V8), 214 bytes

-1 thanks to @l4m2

Quite long, but fast (to some extent).

n=>(F=(a,g=a[n*n]=n,i=-1,k=a.find(x=>x>!!++i))=>k?(g=j=>--j+k&&g(j,a[i+j]||F(b=[...a],b[b[i+j]=j*=j>0||-1,i]-=j)))(k):F[s=/1.*1|1/.exec(a.join``)[0]]||print(F[s]=F[[...s].reverse().join``]=s))(Array(n*n*2).fill(0))

Try it online!

Check the number of solutions up to n=10

Method

As illustrated on the OEIS page, we start with all frogs in a single place and make a tree of all possible reverse moves with a breadth-first search:

                     _____________4____
                    /             |    \
               ___3001___        202    13
              /   |  |   \      /   \    |
        201001 12001 2101 1021 1102 112 121
       /   |     |         |    |
1101001 111001 11101      1111 11011

Implementation

We start with an array of size \$2n^2\$ filled with 0's, except the entry at position \$n^2\$ (0-indexed) which is set to \$n\$.

At each iteration, we look for the first value \$k>1\$ in the array and try to move \$1\$ to \$k-1\$ frogs from there to empty lily pads, in both directions. Each move is a recursive call to the function \$F\$ with an updated copy of the array.

Once there are only 0's and 1's remaining in the array, we trim the leading and trailing 0's and check whether the resulting pattern was already encountered. If not, we print the pattern and save it along with its reversed counterpart, so that neither is printed again.

\$\endgroup\$
6
  • \$\begingroup\$ Your solution is actually quite fast and doesn't seem to need that much main memory. Do you think you could use it to calculate values ​​n > 18 and donate them to the OEIS? \$\endgroup\$ Commented Nov 26 at 18:54
  • \$\begingroup\$ @SophiaAntipolis That's still inefficient golfed code and Node.js is not the best option for speed anyway. I'd be willing to bet that the highest existing terms on OEIS were already computed with faster code. (But I can certainly let it run for a while on my laptop and see what happens.) \$\endgroup\$
    – Arnauld
    Commented Nov 26 at 19:09
  • \$\begingroup\$ @SophiaAntipolis With better cache management (not limited to leaf nodes) and some other optimizations, I can reach N=15 in about 1 minute on my laptop, after which I run out of memory (there's actually an internal limit in Node.js that is reached well before the RAM is full). From what I see, I would say a rough estimate of the computation time to reach N=19 would be a little under 24 hours -- but that assumes infinite memory. \$\endgroup\$
    – Arnauld
    Commented Nov 26 at 21:27
  • \$\begingroup\$ And without any extra cache, I think it would still not be able to 'remember' all the existing solutions for N≥17. To put it simply, this is not the right algorithm -- and probably not the right language -- to reach high values. \$\endgroup\$
    – Arnauld
    Commented Nov 26 at 21:37
  • \$\begingroup\$ Thank you for your research! \$\endgroup\$ Commented Nov 27 at 16:39
5
\$\begingroup\$

Python 3, 216 204 196 bytes

-8 bytes thanks to @Unrelated String

g=lambda*y:{z for i in range(len(y))for v in(y,y[::-1])for n in range(1,v[i])for z in g(*(i<n or 1>v[i-n])*(*v[:i][:-n],n,*(n+~i)*[0],*v[:i][1-n or i:],v[i]-n,*v[i+1:]))}-{y[1:]}or{min(y,y[::-1])}

Try it online!

The gnarly one liner always wins in the end.

Uses the same backwards search as found on the OEIS page.

\$\endgroup\$
3
  • \$\begingroup\$ 195. Not entirely sure why (1,)>v[i-n:-1] works, but i<n or 1>v[i-n] is only one byte longer. \$\endgroup\$ Commented Nov 28 at 20:14
  • 1
    \$\begingroup\$ @UnrelatedString In most cases it makes sense, if i-n indexes a 0 element then the resulting list slice starts with a 0 and we get True. But if i-n itself is less than 0 then it breaks down, since the slice will refer to that distance from the end of the list. I will admit that I haven't found any cases where it doesn't work, but I can't see any reason it should always theoretically work so I didn't include it. \$\endgroup\$ Commented Dec 2 at 16:31
  • 1
    \$\begingroup\$ My thoughts exactly... It's worth noting that it doesn't really get questionable until i-n is less than -1, since the empty slice [-1:-1] is guaranteed to compare less than (1,) as well, but it seems like the comparison is in fact not equivalent most of the time when it's -2 or lower and for some reason that just... ends up not mattering. Weird stuff. \$\endgroup\$ Commented Dec 3 at 14:36
4
\$\begingroup\$

Charcoal, 85 bytes

NθFΦEX²Σ…⁰⊕θ↨⊕⊗ι²›⁼θΣι‹ι⮌ι«≔⟦ι⟧υFυ«≔⌕AX⁰κ⁰ηFηFΦη⁼§κλ↔⁻λμ⊞υEκ⎇⁻ξμ∧⁻ξλν⁺ν§κλ»¿⊙υ№κθ⟦⪫ιω

Try it online! Link is to verbose version of code. Explanation:

Nθ

Input n.

FΦEX²Σ…⁰⊕θ↨⊕⊗ι²›⁼θΣι‹ι⮌ι«

Make bit strings of up to length 1+T(n) ( would save 2 bytes but take too long on TIO) which both start and end in 1 plus have n bits in total and do not already appear as a reversal.

≔⟦ι⟧υFυ«

Start a breath-first search for parties.

≔⌕AX⁰κ⁰η

Find the list of valid sources and destinations.

FηFΦη⁼§κλ↔⁻λμ

Find those sources and destinations that are an exact hop away.

⊞υEκ⎇⁻ξμ∧⁻ξλν⁺ν§κλ

Calculate the position after the hop and add it to the search list.

»¿⊙υ№κθ

If any position is a party, then...

⟦⪫ιω

... output the original bit string.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ I am always deeply impressed by how quickly the members on this list find solutions. Chapeau! \$\endgroup\$ Commented Nov 26 at 14:29
  • \$\begingroup\$ @SophiaAntipolis I didn't even look at the OEIS page... probably that would result in a shorter solution. \$\endgroup\$
    – Neil
    Commented Nov 26 at 18:53
  • \$\begingroup\$ @SophiaAntipolis Huh, I tried it and it actually came out to 103 bytes although it is much faster of course: Try it online! \$\endgroup\$
    – Neil
    Commented Nov 26 at 23:37
4
\$\begingroup\$

Haskell, 240 bytes

g.h.pure
h l|all(<2)l=[show=<<l]|m<-length l-1=[r|(i,k)<-zip[0..]l,k>1,j<-[1..k-1],d<-[i+j,i-j],d<0||d>m||l!!d<1,r<-h[last$0:[l!!x|elem x[0..m]]++[k-j|x==i]++[j|x==d]|x<-[min 0 d..max d m]]]
g(a:r)=a:g(filter(`notElem`[a,reverse a])r)
g e=e

Try it online!

Starts with a party and backtracks to find all possible starting positions.

The h function takes a list of frog counts and returns a list of starting positions that can lead to that position. First we check if all the frogs are alone; if so we simply return the input as binary string in a singleton list. Otherwise we iterate over each position that has k frogs (where k is at least 2) and send j of them j positions left or right (where j is at most k-1 so we always leave at least one frog behind) as long as the landing spot is empty. Then we recur with that new position.

Finally all we have to do is filter out all the repetitions.

\$\endgroup\$
2
\$\begingroup\$

Python3, 369 bytes

def f(n):
 q,s,r=[([],n,0)],[],[]
 for a,b,t in q:
  if b:q+=[(a+[1],b-1,0)]
  if t<n-1 and b and a:q+=[(a+[0],b,t+1)]
  if b==0 and a[::-1]not in s:
   s+=[a[::-1],a];Q,S=[a],[a]
   for u in Q:
    if u.count(0)==len(u)-1:r+=[a];break
    for i,j in enumerate(u):
     for I in[-1,1]:
      if 0<=(V:=I*j+i)<len(u)and u[V]:U=[*u];U[i]=0;U[V]+=j;Q+=[U];S+=[U]
 return r

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You can removed the spaces at t<n-1 and and b==0 and for -2 bytes; you can change the if 0<= to if-1< for another -1 byte; and you can change the and b and a to and b*a for another -4 bytes. \$\endgroup\$ Commented Nov 26 at 15:21
  • \$\begingroup\$ -2 bytes: q,s,r=[([],n,0)],[],[] --> q,s,*r=[([],n,0)],[]. \$\endgroup\$ Commented Nov 26 at 18:02
0
\$\begingroup\$

JavaScript (V8), 173 bytes

n=>(g=(a,i=0,A=[...a].reverse(),h=t=>--a[i]&&h(++t,a[t]=a[t]||(a[t]=t-i,g([...a]))))=>1/a[i]?a[i]>1?h(i,A&&g(A,a.length+~i,0)):g(a,i+1):g[a]||print(g[a]=g[A]=a.join``))([n])

Try it online!

Idea of Arnauld, split the first group of ≥2

Handle jump backward, then reverse the array and still handle jump backwards, since it's easier to append at end.

Should be faster than Arnauld's since shorter array. Because of too many execution of reverse it can be slower. g(a,i+1) => g(a,i+1,A) to accelerate

\$\endgroup\$
1
  • \$\begingroup\$ "fasten" means to attach e.g. with buttons; did you mean "speed up"? \$\endgroup\$
    – Neil
    Commented Dec 7 at 9:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.