| Bytes | Lang | Time | Link |
|---|---|---|---|
| 032 | Pip xp | 210815T205457Z | DLosc |
| 039 | BQN | 210914T070059Z | frasiyav |
| 146 | jq | 210913T205918Z | Michael |
| 131 | C gcc | 210818T054501Z | att |
| 023 | Husk | 210816T232306Z | Dominic |
| 099 | R | 210816T200456Z | pajonk |
| 022 | Jelly | 210816T232807Z | Jonathan |
| 145 | PowerShell Core | 210817T015901Z | Julian |
| 5348 | J | 210815T201547Z | xash |
| 022 | 05AB1E | 210816T235830Z | ovs |
| 026 | Jelly | 210816T231821Z | Nick Ken |
| 137 | C clang | 210816T183500Z | AZTECCO |
| 091 | Ruby | 210816T073712Z | G B |
| 092 | JavaScript ES6 | 210815T220255Z | Arnauld |
| 058 | Haskell + hgl | 210815T214912Z | Wheat Wi |
| 042 | Charcoal | 210815T214033Z | Neil |
| 116 | Python 3 | 210815T200646Z | hyperneu |
Pip -xp, 32 bytes
^:iT(Yy+a@y%:#a)NiiPBya@i^@:i@?y
Takes the list (formatted like so: [1;2;-3]) as a command-line argument, and outputs a list of two lists. Attempt This Online! Or, verify all test cases.
Explanation
^:iT(Yy+a@y%:#a)NiiPBya@i^@:i@?y
a is cmdline input, eval'd (-x flag);
i is 0, y is "" (implicit)
^:i Split i and assign back to i: i is now [0]
T Loop until
y current index
+a@y plus number at current index
%: mod
#a length of list
Y (yank into y, making this the new index)
( )Ni is already in the list of indices traversed:
iPBy Push the new index onto the list of indices
After the loop, we have the list of unique
indices traversed in i and the first repeated
index in y
a@i Values from a at each index in i
^@: split at
i@?y the index of y in i
BQN, 39 bytesSBCS
↕∘≠⊸{⊏⟜𝕩¨2↑⊒⊸/⊸(+`⊑⊸=)⊸⊔0∾⊑˜⍟𝕨⟜⊑≠⊸|𝕨+𝕩}
↕∘≠⊸{⊏⟜𝕩¨2↑⊒⊸/⊸(+`⊑⊸=)⊸⊔0∾⊑˜⍟𝕨⟜⊑≠⊸|𝕨+𝕩} # 𝕩 is input, 𝕨 is indices 0,1,..,length-1
↕∘≠⊸{ } # pass indices into the main function as 𝕨
≠⊸|𝕨+𝕩 # add indices to the input mod the length
⊑˜⍟𝕨⟜⊑ # traverse from the first element a number
# of steps equal to the length,
# accumulating results
0∾ # prepend 0
⊒⊸/⊸(+`⊑⊸=)⊸⊔ # find the first value to repeat and
# partition by occurrences
2↑ # take the first 2 groups
⊏⟜𝕩¨ # and use them to index into the input
jq, 146 bytes
length as$l|def x:((.[0]+.[1][-1])%$l+$l)%$l;def n:x as$x|.[1]|index($x);. as$i|[0,[],[]]|until(n;[$i[x],.[1]+[x],.[2]+[$i[x]]])|.[2][:n],.[2][n:]
C (gcc), 115 131 bytes
f(r,n,o,l,j)int*r,**o,*l;{int*t=malloc(4*n);for(*l=j=0;j+=o[0][(t[j]=++*l)-1]=r[j],!t[j=(j%n+n)%n];);*l-=l[1]=t[j]-1;o[1]=*o+l[1];}
Outputs [prefix, loop] into o and [len(loop), len(prefix)] into l. Expects these to have allocated enough memory to fit the output (though o[1] is discarded).
Husk, 32 29 25 23 bytes
Edit: -2 bytes thanks to Razetime
†!¹G-§eoUṠ-UUm←¡Sṙo!¹←ŀ
Outputs loop first, then first-visited.
Piece by piece:
Make an infinite list of lists of indices by repeatedly shifting by the input value indexed by the first element:
¡Sṙo!¹←ŀ
And get the first element of each of these: this is the list of indices:
m←
Now, get the longest non-repeating prefix (this includes one copy of the repeating elements):
U
And get the repeating indices:
oUṠ-U
Join these together into a list of 2 lists:
§e
And remove the first (the repeating indices) from the second (the prefix):
G-
Finally, use these to index into the original input:
†!¹
R, 121 118 108 102 101 99 bytes
-10 bytes and another -6 thanks to @Dominic van Essen
function(a,t=1){while(!(t=(t+a[t]-1)%%sum(a|1)+1)%in%T)T=c(T,t)
split(a[T],cut(cumsum(T==t),-1:1))}
The outputted lists have weird names (two intervals), but it I hope it's ok.
Jelly, 23 22 bytes
Quite possibly still beatable...
ĖUṙFḢƊƬḢ€⁺JœṖ€$§ṪọɗƇLṪ
A monadic Link that accepts the list and yields a list of lists.
How?
ĖUṙFḢƊƬḢ€⁺JœṖ€$§ṪọɗƇLṪ - Link: list of integers A=[a,b,...,x,y,...]
Ė - enumerate -> [[1,a],[2,b],...,[n,x],[m,y],...]
U - upend -> [[a,1],[b,2],...,[x,n],[y,m],...]
Ƭ - collect until a repeat under:
Ɗ - last three links as a monad, f(current=[[x,n],[y,m],...]):
F - flatten (current) -> [x,n,y,m,...]
ṙ - rotate (current) left by (each of [x,n,y,m,...])
Ḣ - head -> rotation by x
Ḣ€ - head each -> leftmost of each, [[a,1],...,[x,n],...]
⁺ - repeat Ḣ€ -> visited elements in order, [a,...,x,...,last_of_loop]
$ - last two links as a monad, f(V=[a,...,x,...,last_of_loop]):
J - range of length -> [1,2,...,length(V)]
œṖ€ - partition (V) before each (of those) indices
Ƈ - filter (all of these 2-partitions) keeping if:
L - use length (of A) on the right of...
ɗ - last three links as a dyad, f(partition, length(A)):
§ - sums
Ṫ - tail -> length of the potential loop
ọ - how many times is that divisible by length(A)?
(positive (truthy) if an actual loop, else 0 (falsey))
Ṫ - tail
PowerShell Core, 156 145 bytes
for($v=@();!(($s=$v.IndexOf($i))+1);$i%=$l){$v+=,+$i
$t+=,($u=$args[+$i])
$i+=$u+($l=$args.Count)}if(--$l*$s){$t[$s..$l],$t[0..--$s]}else{$t,@()}
Takes a list as parameter.
Returns two lists: loop first then trajectory
Saved:
- 2 bytes by swapping the loop / trajectory in the result
- 2 bytes by reusing
$args[$i]as$u - 1 byte by merging the declaration and first usage of
$l - 3 bytes by not initialising
$ianymore - 3 bytes thanks to mazzy!
Not golfed:
$index = 0
$length = $args.Count
for ($indices = @(); ($truncateAt = $indices.IndexOf($index)) -eq -1) {
$indices += , $index
$trajectory += , $args[$index]
$index = ($index + $args[$index] + $length) % $length
}
if (--$length -and $truncateAt) {
($trajectory[0..--$truncateAt] -join ','), ($trajectory[++$truncateAt..$length] -join ',')
}
else {
'', ($trajectory -join ',')
}
J, 53 48 bytes
-5 thanks to Jonah!
(_2{.{~</.~]+./\@e.r)(]~.@,r=.(#@[|]+{~){:)^:_&0
r=.(#@[|]+{~){:take the last index (starting with 0&0), get the corresponding value, add it to the index and take the mod.]~.@, … ^:_append the new value to the indices list and repeat that process until the list does not change after removing duplicates]+./\@e.rthe next index is a duplicate, so we find it in the indices list and have a bitmask: 0 for visited once, 1 for loops._2{.{~</.~group the values based on the indices. Because there might be no items that are visited once, we can pad the output with taking the last two items_2{.
Another approach would be to not build a list, but just repeat the index-shift-mod-loop <@# times, keeping the results, and then search for the loop. But I didn't get it shorter than this.
Jelly, 26 bytes
L‘0ị+ị¥%L}ɗƬɗƬ%LḊḣ2fQ,ḟʋ/ị
A monadic link taking a list of integers and returning two lists of integers, with the looped integers first.
C (clang), 137 bytes
a,i,j;
#define f(l,z){int t[z]={i=j=0},h[z];for(;!(a=t[i]);i=(z+i+l[i]%z)%z)h[j]=l[i],t[i]=++j;for(i=0;i<j;)printf("! %d"+!!--a,h[i++]);}
l : list , z : length
int t[z] : kinda sieve, every step sets the visited item to step number
h[z] : save the trajectory values in order for output
for(;!(a=t[i]) : we iterate until we find a visited item, saving in a the first already visited
;i=(z+i+l[i]%z)%z) : modulo hack
at each iteration :
h[j]=l[i] : add item to output list
,t[i]=++j; : and update sieve
Output
for(i=0;i<j;) : j is the number of items visited
printf("! %d"+!!--a,h[i++])
a is the beginning of loop so we
put a separator by including '!' in format string
Ruby, 91 bytes
->l{*r=a=b=0;r<<a until b=r.index(a=(a+l[a])%l.size);[z=r[0,b],r-z].map{|x|l.values_at *x}}
JavaScript (ES6), 92 bytes
a=>[(g=p=>a=1/(i=g[p%=w=a.length])?[]:[q=a[p],...g(p+q+w*q*q,g[p]=k++)])(k=0).splice(0,i),a]
Commented
a => [ // a[] = input array
( g = p => // g is a recursive function taking a position p
// the underlying object of g is also used to keep
// track of the positions that are visited
a = // update a[]
1 / ( //
i = g[ // reduce the position modulo the length w of the
p %= w = // array and load g[p] into i
a.length //
] //
) ? // if i is defined:
[] // we've found the loop: stop the recursion
: // else:
[ // update the output array:
q = a[p], // load a[p] into q
...g( // do a recursive call:
p + q + // add q to p
w * q * q, // also add w*q² to make sure it's >= 0
g[p] = k++ // save the index k into g[p] and increment k
) // end of recursive call
] // end of array update
)(k = 0) // initial call to g with p = k = 0
.splice(0, i), // extract the non-looping part
a // append the looping part
] //
Haskell + hgl, 61 60 58 bytes
(i:y)#x|i?>y=m(x!)&@sp(/=i)(rv y)|u<-(i+x!i)%l x:i:y=u#x
([0]#)
hgl is an experimental golfing library I am developing for Haskell. I started a few days ago and this is my first answer, and it's proof there is still a lot of room for improvement.
From this post I've learned that:
- I should probably make a dedicated function for
m.(!), since it is likely to come up more than just here. - I need versions of
sp(span) andbk(break) that include the element that matches / doesn't match the predicate in the first part. I had to use a hack withrv, which is costly and only works in this specific scenario. I should make an infix version ofTurns out I had already done this (e(elem). It would have saved me at least a byte here.(?>)). Maybe what I actually need is better documentation that makes it easier to find this stuff.I should make an infix version ofThis also existed and I didn't realize (jB. It would have saved me at least 2 bytes here.(&@)). There might be a pattern here.- It might be a good idea to make an infix of
sp. It could have saved me a byte here if I hadn't made an infix ofjB. - I have probably overall underestimated the usefulness of infixes and I should in general just make more of them.
But here's how it actually works:
Vocab:
(?>): checks if a list contains an element (elem)m: map (fmap)(!): index a list (sort of(!!))(&@): maps function across both parts of a tuple.sp: splits a list at the first element that matches a predicate (span)rv: reverses a list (reverse)(%): modulo infix (mod, yes Haskell does not have a modulo infix)
So this builds up a list of indices, when a index is added that is already in the list it stops and splits at the last occurrence of that index, and converts the indices to their values.
Charcoal, 42 bytes
≔⁰ζW¬№υζ«⊞υζ≔﹪⁺ζ§θζLθζ»≔⌕υζζUMυ§θιI⟦…υζ✂υζ
Try it online! Link is to verbose version of code. Explanation:
≔⁰ζ
Start at index 0.
W¬№υζ«
Repeat until a duplicate index is found.
⊞υζ
Save the current index.
≔﹪⁺ζ§θζLθζ
Calculate the new index.
»≔⌕υζζ
Find the position of the repeat.
UMυ§θι
Replace the indices with the values.
I⟦…υζ✂υζ
Output the values before and after the repeat as separate arrays.
Python 3, 116 bytes
f=lambda a,i=0,k=[]:i in k and[[a[q]for q in x]for x in[k[:k.index(i)],k[k.index(i):]]]or f(a,(i+a[i])%len(a),k+[i])