Challenge
For any two non-empty strings A and B, we define the following sequence :
F(0) = A
F(1) = B
F(n) = F(n-1) + F(n-2)
Where +
denotates the standard string concatenation.
The sequence for strings "A" and "B" starts with the following terms: A, B, BA, BAB, BABBA, ...
Create a function or program that, when given two strings A
and B
, and a positive integer I
returns the I
-th character of F(∞)
.
You may choose to use 0-indexing or 1-indexing for I
, just specify it in your answer.
You may assume the strings contain only uppercase (or lowercase) letters.
This is a variation of Project Euler's Problem 230, where the two strings were strings of digits of equal length, which trivialize the problem.
Input/Output
You may choose any format for the input. The output should only contain the desired character, with trailing spaces/newlines allowed.
Test Cases
ABC, DEF, 1234567890 → A
ACBB, DEFGH, 45865 → B
A, B, 3 → B
ABC, DEF, 10 → E
This is code-golf, so the lowest byte count for each language wins!
11 Answers 11
Haskell, 15 bytes
a#b=b++b#(a++b)
Takes strings a
and b
as input, returns the whole infinite Fibonacci word, as is usually allowed in sequence challenges.
How?
Not much to say. This answer relies on the identity $$ F(a,b)=b+F(b,a+b), $$ where \$F(a,b)\$ is the infinite Fibonacci word with starting words \$a\$ and \$b\$.
-
1\$\begingroup\$ Just a reminder that marking something as non-competitive does not allow it to be invalid, so if it turns out that it isn't allowed to output
F(∞)
, then you should modify your answer :) \$\endgroup\$2021年04月12日 17:33:47 +00:00Commented Apr 12, 2021 at 17:33 -
\$\begingroup\$ @cairdcoinheringaahing Duly noted :( \$\endgroup\$Delfad0r– Delfad0r2021年04月12日 17:42:20 +00:00Commented Apr 12, 2021 at 17:42
Jelly, (削除) 6 (削除ここまで) 5 bytes
9;¡5ị
Uses 1 indexing
-1 byte thanks to Jonathan Allan, noticing that we could avoid 5
becoming the right argument to ;¡
by forcing ;¡
into a nilad-dyad pair with 9
!
Dyadic ¡
is essentially Jelly's generalised Fibonacci operator
How it works
9;¡5ị - Main link. Takes A on the left, B on the right and I as the third argument
9 - Set the return value to B
¡ - I times do the following, swapping the updated arguments each time:
; - Concatenate the arguments
5ị - Yield the i'th character of the result
When ;¡
is run with 2 arguments, it does the following (calling the initial left argument B
and the initial right argument A
, as 9
essentially "swaps" the order of the arguments. We'll do 3 iterations):
- Iteration 1:
;
concatenatesB
andA
, yieldingBA
. We then moveB
to the right and takeBA
as our left argument for the next iteration - Iteration 2:
;
concatenatesBA
andB
, yieldingBAB
. Our arguments becomeBAB
on the left andBA
on the right - Iteration 3:
;
concatenatesBAB
andBA
, yieldingBABBA
. This is the last iteration, so we returnBABBA
-
\$\begingroup\$ 5 bytes using a leading constant chain instead with
9;¡5ị
- TIO. \$\endgroup\$Jonathan Allan– Jonathan Allan2021年04月12日 18:02:16 +00:00Commented Apr 12, 2021 at 18:02 -
\$\begingroup\$ @JonathanAllan That's a brilliant catch, thanks! \$\endgroup\$2021年04月12日 18:03:19 +00:00Commented Apr 12, 2021 at 18:03
-
\$\begingroup\$ Now we need tribonacci version to make the
¡
unusable :P \$\endgroup\$Bubbler– Bubbler2021年04月13日 00:25:31 +00:00Commented Apr 13, 2021 at 0:25
Python 3, 36 bytes
f=lambda a,b,i:b[i:i+1]or f(b,b+a,i)
-8 bytes thanks to dingledooper
(削除) Not a particularly creative approach. In fact, basically this is just what l4m2 did but Python will error when accessing out of bounds instead of returning Using undefined
. (削除ここまで)b[i:i+1]
returns b[i]
(for strings) if it's in range, but doesn't error and instead gives ""
if it's out of range. Thanks to dingledooper for that.
Go upvote this answer too. This isn't really intentionally a port because I thought of the same idea but it's an identical approach.
-
3\$\begingroup\$ Does
f=lambda a,b,i:b[i:i+1]or f(b,b+a,i)
work for 36 bytes? \$\endgroup\$dingledooper– dingledooper2021年04月12日 17:34:51 +00:00Commented Apr 12, 2021 at 17:34 -
\$\begingroup\$ @dingledooper yes, that's clever. thanks! \$\endgroup\$2021年04月12日 19:40:02 +00:00Commented Apr 12, 2021 at 19:40
-
\$\begingroup\$ This answer fails for the last string.... \$\endgroup\$wasif– wasif2021年04月12日 15:59:23 +00:00Commented Apr 12, 2021 at 15:59
-
\$\begingroup\$ @Wasif Because of insufficant RAM \$\endgroup\$l4m2– l4m22021年04月12日 16:01:06 +00:00Commented Apr 12, 2021 at 16:01
-
\$\begingroup\$
n=>g=a=>b=>b[n]||g(b)(b+a)
\$\endgroup\$tsh– tsh2021年04月13日 02:18:59 +00:00Commented Apr 13, 2021 at 2:18
Husk, 5 bytes
A rip-off of Delfad0r's beautiful Haskell answer. Go upvote that!
S+S0+
Returns the entire infinite string/list.
S+S0+ a b
is (S+) ((S0) (+a)) b
, which expands to (+b) ((S0 (+a)) b)
(where 0
is a self-reference to the main function) and then to (+b) (0 b (+a b))
, which is basically b + F(b, a + b)
.
Safer answer, 8 bytes
!1
S+S1+
This one gets the Ith character, at the cost of 3 bytes.
-
\$\begingroup\$ The non-
fix
method is shorter here: Try it online! \$\endgroup\$Razetime– Razetime2021年04月12日 16:32:23 +00:00Commented Apr 12, 2021 at 16:32 -
\$\begingroup\$ @Razetime ...wow. Do you want to post that as your own answer? \$\endgroup\$user– user2021年04月12日 16:33:11 +00:00Commented Apr 12, 2021 at 16:33
-
1\$\begingroup\$ nah, feel free to modify. \$\endgroup\$Razetime– Razetime2021年04月12日 16:36:31 +00:00Commented Apr 12, 2021 at 16:36
-
1\$\begingroup\$ Unfortunately both options seem to return 'A' for input 'ABC','DEF',1 while they should return 'D' instead. They are also not equivalent to each other for other inputs \$\endgroup\$Leo– Leo2021年04月12日 22:44:49 +00:00Commented Apr 12, 2021 at 22:44
-
1\$\begingroup\$ That's very nice! I was struggling to find a short solution for this... The only problem with both this and the Haskell answer is that the challenge does not explicitly allow printing the full sequence... I hope they'll change their mind, but at worst this would be fixable with just 2 or 3 extra bytes \$\endgroup\$Leo– Leo2021年04月12日 23:57:39 +00:00Commented Apr 12, 2021 at 23:57
R, (削除) 96 (削除ここまで) (削除) 92 (削除ここまで) 84 bytes
function(A,B,I,`!`=function(k)"if"(k,"if"(k>1,paste0(!k-1,!k-2),B),A))substr(!I,I,I)
Takes I
1-indexed.
-8 bytes thanks to @Dominic
-
1\$\begingroup\$ At risk of outgolfing my own attempt, I think you can save a few bytes using
substr
instead ofstrsplit
: try it... \$\endgroup\$Dominic van Essen– Dominic van Essen2021年04月13日 11:05:25 +00:00Commented Apr 13, 2021 at 11:05
05AB1E, (削除) 6 (削除ここまで) 5 bytes
-1 byte by assuming the input words consist only of letters (è
implicitly swaps arguments if the first one doesn't look like a number)
Takes inputs [A, B]
and n
.
λèì}è
Commented:
λè } # get the nth element of the sequence generated by:
ì # prepending the current string to the last string
# that starts with [A, B]
è # index with n into the nth element of the sequence
Charcoal, 42 bytes
≔−NLζθ≔0εW¬‹θ0«F¬&ε⊗ε≧−+Lζ∧%ε2Lηθ≦⊕ε»§+ηζθ
Try it online! Link is to verbose version of code. Takes the index as the first input. Explanation: I wanted to avoid building up a humunguous string but the code is still slow because I don't know a good way of calculating Fibbinary numbers.
≔−NLζθ
Subtract the length of B
from n
.
≔0ε
Start enumerating Fibbinary numbers.
W¬‹θ0«
Repeat until n
is negative.
F¬&ε⊗ε
Is the current index a Fibbinary number?
≧−+Lζ∧%ε2Lηθ
If so then subtract the length of either B
or BA
from n
depending on whether the current index is even or odd.
≦⊕ε
Increment the index.
»§+ηζθ
Output the n
th character of AB
(since n
is negative here, Charcoal counts back from the end).
R, (削除) 76 (削除ここまで) 66 bytes
Edit: -10 bytes thanks to Giuseppe
f=function(b,a,n)`if`(nchar(b)>n,substr(b,n,n),f(paste0(b,a),b,n))
Recursive function: input the starting strings b
and a
(note reversed order), and the 1-based index to output.
Could be a bit shorter (53 bytes) if inputs are vectors of characters instead of strings.
R, 48 bytes
function(a,b)repeat{c=b;cat(b<-paste0(b,a));a=c}
Prints the infinite string.
-
-
\$\begingroup\$ @Giuseppe - Oh, for goodness sake! That's so obvious now you've suggested it! Thanks! \$\endgroup\$Dominic van Essen– Dominic van Essen2021年04月13日 11:19:07 +00:00Commented Apr 13, 2021 at 11:19
PowerShell, 63 bytes
param($x,$y,$n)$a=$x,$y
1..$n|%{$a+=$a[$_]+$a[$_-1]}
$a[-1][$n]
-11 bytes thanks to julian
-
1
-
\$\begingroup\$ "You may choose any format for the input." - Try it online! \$\endgroup\$mazzy– mazzy2021年04月13日 04:32:36 +00:00Commented Apr 13, 2021 at 4:32
Java (JDK), 70 bytes
(a,b,n)->{for(var t=a;b.length()<=n;a=b,b=t)t=b+a;return b.charAt(n);}
ABC
,DEF
, 10? \$\endgroup\$