# Slice, Slice, Maybe

Everyone loves slicing in python, as in array to access the fifth element or array[:5] to access the zero through fourth element or array[::-1] to reverse an array. However, these all have seemingly distinct notations. When and where should the colons and integers be placed?

Your task is to change any valid slice syntax into a slice with as many colons and integers as possible. To help with that, we will make some definitions. Valid slice syntax is anything directly after "Given a slice" in this section.

Define <POS> to be any positive integer, that is any digit 1-9 followed by any amount of digits 0-9.

Define <NEG> to be any negative integer, that is a - followed by <POS>

Define <INT> to be <POS>, <NEG>, or <ZERO>

Define sgn(a) to be the sign of a: 1 for positive a, -1 for negative a, and 0 for a=0.

For all of the following, a and b are <INT> and c is <POS> or <NEG> unless otherwise specified.

• Given a slice [], your program may have undefined behavior.
• Given a slice [a], your program or function must return [a:a+k:c] for some <POS> or <NEG> value of c and 0 < abs(k) <= abs(c) and (a+k < 0 if c < 0) and (a+b > 0 if c > 0)
• Given a slice [:], your program must return [0::1].
• Given a slice [a:], your program must return [a::1].
• Given a slice [:b], your program must return [0:b:1].
• Given a slice [a:b] where a < b and sgn(a)+sgn(b) != 0 your program must return [a:b:1].
• Given a slice [::], your program must return [0::1].
• Given a slice [a::], your program must return [a::1].
• Given a slice [:b:], your program must return [0:b:1].
• Given a slice [::c], your program must return [0::c] if c is <POS> and [-1::c] otherwise.
• Given a slice [a:b:] where a < b and sgn(a)+sgn(b) != 0, your program must return [a:b:1].
• Given a slice [a::c], your program must return [a::c].
• Given a slice [:b:c], your program must return [0:b:c] if c is <POS> and [-1:b:c] otherwise.
• Given a slice [a:b:c] your program must return [a:b:c].

# Example

The "slice"  gives the fifth element of an array.

Your program or function can output [5:6:1] or [5:7:2] or [5:1000:1000] or [5:4:-1] or [5:0:-5].

The program cannot output [5:7:1] or [5:-6:1] or [5:-6:-1] or [5:6:-1].

# Test Cases

Input     Output
       [1:2:1]     [Output may vary]
[-1]      [-1:-2:-1]  [Output may vary]
[:]       [0::1]
[1:]      [1::1]
[-1:]     [-1::1]
[0:3]     [0:3:1]
[-3:-1]   [-3:-1:1]
[::]      [0::1]
[0::]     [0::1]
[:5:]     [0:5:1]
[::2]     [0::2]
[::-2]    [-1::-2]
[2:4:]    [2:4:1]
[2::3]    [2::3]
[:2:1]    [0:2:1]
[:2:-1]   [-1:2:-1]
[1:2:3]   [1:2:3]


# Rules

• You do not have to do any input validation.
• The output and input may include or exclude the brackets [].
• The output and input may be a 3-tuple instead of a :-delimited string.
• This is , so shortest code in each language wins.
• Did anyone else read the title in the same way you'd say "Ice, Ice, Baby!" Aug 29, 2017 at 11:41
• @KevinCruijssen That was my intention :) Aug 29, 2017 at 16:34
• Although you haven't logged on since September, I am wondering how exactly the 3-tuple I/O option is supposed to work... are blanks before/after colons represented by arbitrary non-integer elements, or does everything have to be a string? Are missing colons represented by a different arbitrary non-integer element, or can input tuples have less than three elements? May 6, 2019 at 3:17
• @UnrelatedString generally, I/O here is permissive, so the answer to your first question is: you can do anything that works for you. On your second question, having an tuple with less than 3 elements would be ambiguous. For example, [a:] and [:b] have different behavior despite having the same elements. May 6, 2019 at 3:37
• Thanks for the quick response, and welcome back! The ambiguity shouldn't be an issue with an element (I'll call it e) that would represent an empty slot, since [a:] would be (a,e) and [:b] would be (e,b), so if that's the only reason not to use variable-size tuples (or nested tuples) then I'll go ahead and do it unless I can think of a more convenient encoding. May 6, 2019 at 4:46

# Python 2, 101969085 82 bytes

def f(r):l=len(r);b=r[l>1]+'1'*(l<2);c=(r+[0,b])or'1';print ror~-('.'<c),b,c


Try it online!

Explanation:

Basically a golfed version of:

f(r):
if len(r)==1:return [r,r+'1',r+'1']            # [a, a1, a1] where a1 is further from 0 than a
if len(r)==2:return [ror'0',r,'1']                # [a or 0, b, 1]
if len(r)==3:return [ror -1*(r<0),r,ror'1'] # [a or 0|-1, b, c or 1]


# Python 3, 268 bytes

import re
w='([^:]*)'
def f(x):
(a,b,c,d,e)=re.findall('$%s(?:(:)%s(?:(:)%s)?)?$'%(w,w,w),x)
g=int(a)if a else(-1if e and int(e)<0else 0)
return'[%s:%s:%s]'%(g,c if c else(g+(1if g>0else-1)if not(b or d)else''),e if e else((1if g>0else-1)if not(b or d)else 1))


Try it online!

# Kotlin 354 330 bytes

## Submission

fun f(i:List<Int?>):List<Int?>?{
val N=null
val Z=mutableListOf(0,N,1)
if(i.none{it!=N})return Z
val v:Int=i?:0
val z:Int=if(i.size==3)i?:1 else 1
val p=if(v<0)-1 else 1
return when(i.size){1->listOf(v,v+p,p)
2->listOf(v, i, z)
3->{if(i==N&&i!=N&&i!!<0)Z=-1
return i.zip(Z).map{it.first?:it.second}}
else->N}}


## Beautified

fun f(input: List<Int?>): List<Int?> {
if (input.none { it != null }) return listOf(0, null, 1)
val item0: Int = input ?: 0
val step: Int = if (input.size == 3) input ?: 1 else 1
val direction = if (item0 < 0) -1 else 1
return when (input.size) {
1 -> listOf(item0, item0 + direction, direction)
2 -> {
listOf(item0, input, step)
}
3 -> {
val D = mutableListOf(0, null, 1)
if (input == null && input != null && input!! < 0) D = -1
return input.zip(D).map { it.first ?: it.second }
}
else -> listOf()
}
}