Find Array Runs
Swift, 246 bytes
func f(_ a:[Int]){
var c=a.count,m=a+a,z=0,r:String=""
for i in 1..<c{m[i]-=a[i-1];if m[i]==m[i-1]{m[i-1]=0}};m[0]=1
for i in 0..<c{if m[i]==0 {z=1}else if z==0{r+=" \(a[i])"}else{r+="to\(a[i])"+(m[i]>1 ? "by\(m[i])":"");z=0;m[i+1]=1}}
print(r)
}
Try it online!
Jelly, 42 40 bytes
-2 thanks to Kevin Cruijssen (filter out twos, ḟ2
, rather than replacing twos with zeros, 2,0y
)
ŒṖIE×LƲ€ḟ2SƊÞṪµ.ịU,Iḟ1ƊQ€Fż“to“by”ṁṖƊ$)K
A full program printing the result.
(As a monadic Link a list containing a mixture of integers and characters would be yielded)
Try it online!
(Too inefficient for the largest test-case to complete within 60s, so I removed [1,2,3,4]
.)
How?
ŒṖIE×LƲ€ḟ2SƊÞṪµ.ịU,Iḟ1ƊQ€Fż“to“by”ṁṖƊ$)K - Main Link: list of numbers
ŒṖ - all partitions
ƊÞ - sort by last three links as a monad:
Ʋ€ - last four links as a monad for €ach:
I - incremental differences (of the part)
E - all equal?
L - length (of the part)
× - multiply
ḟ2 - filter discard twos
S - sum
Ṫ - tail (gets us the desired partition of the input)
µ ) - perform this monadic chain for €ach:
. - literal 0.5
ị - index into (the part) - getting [tail,head]
U - upend - getting [head,tail]
Ɗ - last three links as a monad:
I - incremental differences (of the part)
1 - literal one
ḟ - filter discard (remove the ones)
, - pair -> [[head,tail],[deltasWithoutOnes]]
Q€ - de-duplicate €ach -> [[head,tail],[delta]] or [[head,tail],[]] or [[loneValue],[]]
F - flatten -> [head,tail,delta] or [head,tail] or [loneValue]
$ - last two links as a monad:
Ɗ - last three links as a monad:
“to“by” - literal list [['t', 'o'], ['b', 'y']]
Ṗ - pop (get flattened result without rightmost entry)
ṁ - mould ["to","by"] like that (i.e. ["to","by"] or ["to"] or [])
ż - zip together
K - join with spaces
- implicit print
K (ngn/k), 102 bytes
{1_,//${H:" ",h:*x;l:+/&\x=h+(!#x)*d:--/2#x;$[l>2;(H;"to";x l-1;(~d=1)#,"by",d;o l_x);l;H,o 1_x;""]}x}
Try it online!