Sign change, loop and display with minimal padding

Input:

Two integers: one negative, one positive.

Output:

On the first line output lowest to highest. On the second line we've removed the highest and lowest numbers and sign-changed all individual numbers. On the third line we've removed the highest and lowest numbers again and sign-changed all individual numbers again. etc. (The example below should make the challenge clearer.)

Important: In addition, we add spaces so the numbers in a column are all aligned (to the right).
The minimal alignment is the main part of this challenge, this means that you can't just make every single number the same width. The width of a column is based on the largest number-width of that specific column (and the sequence with sign-change is to give the numbers some variety in width per column).

For example:

Input: -3,6

Output:
-3,-2,-1, 0, 1, 2, 3, 4,5,6   // sequence from lowest to highest
2, 1, 0,-1,-2,-3,-4,-5       // -3 and 6 removed; then all signs changed
-1, 0, 1, 2, 3, 4             // 2 and -5 removed; then all signs changed again
0,-1,-2,-3                   // -1 and 4 removed; then all signs changed again
1, 2                         // 0 and -3 removed; then all signs changed again
// only two numbers left, so we're done


As you can see above, spaces are added at the positive numbers, when they share a column with negative numbers to compensate for the - (the same would apply to 2-digit numbers).

Challenge rules:

• Input must be two integers
• You can assume these integers are in the -99-99 (inclusive) range.
• The first integer will be negative, and the other will be positive.
• Output can be in any reasonable format, as long as it's clear there are rows and rightly aligned columns: I.e. STDOUT; returning as String with newlines; returning as list of Strings; etc. Your call.
• The output must also contain a delimiter of your own choice (except for spaces, tabs, new-lines, digits or -): I.e. ,; and ; and |; and X; etc. are all acceptable delimiters.
• The output lines may not contain a leading or trailing delimiter.
• The output may contain ONE trailing new-line, and any line may contain any number of trailing spaces.

General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
• Default Loopholes are forbidden.

Test cases:

Input: -3,6

Output:
-3,-2,-1, 0, 1, 2, 3, 4,5,6
2, 1, 0,-1,-2,-3,-4,-5
-1, 0, 1, 2, 3, 4
0,-1,-2,-3
1, 2

Input: -1,1

Output:
-1,0,1
0

Input: -2,8

Output:
-2,-1, 0, 1, 2, 3, 4, 5, 6,7,8
1, 0,-1,-2,-3,-4,-5,-6,-7
0, 1, 2, 3, 4, 5, 6
-1,-2,-3,-4,-5
2, 3, 4
-3

Input: -15,8

Output:
-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6,7,8
14, 13, 12, 11, 10,  9, 8, 7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7
-13,-12,-11,-10, -9, -8,-7,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6
12, 11, 10,  9,  8,  7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5
-11,-10, -9, -8, -7, -6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4
10,  9,  8,  7,  6,  5, 4, 3, 2, 1, 0,-1,-2,-3
-9, -8, -7, -6, -5, -4,-3,-2,-1, 0, 1, 2
8,  7,  6,  5,  4,  3, 2, 1, 0,-1
-7, -6, -5, -4, -3, -2,-1, 0
6,  5,  4,  3,  2,  1
-5, -4, -3, -2
4,  3

Input: -3,15

Output:
-3,-2,-1, 0, 1, 2, 3, 4,  5, 6,  7,  8,  9, 10, 11, 12, 13,14,15
2, 1, 0,-1,-2,-3,-4,-5, -6,-7, -8, -9,-10,-11,-12,-13,-14
-1, 0, 1, 2, 3, 4, 5, 6,  7, 8,  9, 10, 11, 12, 13
0,-1,-2,-3,-4,-5,-6,-7, -8,-9,-10,-11,-12
1, 2, 3, 4, 5, 6, 7, 8,  9,10, 11
-2,-3,-4,-5,-6,-7,-8,-9,-10
3, 4, 5, 6, 7, 8, 9
-4,-5,-6,-7,-8
5, 6, 7
-6

Input: -12,12

Output:
-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,  9, 10,11,12
11, 10,  9, 8, 7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11
-10, -9, -8,-7,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10
9,  8,  7, 6, 5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7,-8,-9
-8, -7, -6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8
7,  6,  5, 4, 3, 2, 1, 0,-1,-2,-3,-4,-5,-6,-7
-6, -5, -4,-3,-2,-1, 0, 1, 2, 3, 4, 5, 6
5,  4,  3, 2, 1, 0,-1,-2,-3,-4,-5
-4, -3, -2,-1, 0, 1, 2, 3, 4
3,  2,  1, 0,-1,-2,-3
-2, -1,  0, 1, 2
1,  0, -1
0

• "Never outside -100-100" does that include never being -100 or 100 too? Mar 9, 2017 at 15:48
• @JonathanAllan I think so. It makes sense excluding -100 and 100, because if they were included, a 3rd/4th digit will be added and everything would be changed for just 2 values Mar 9, 2017 at 18:05
• Related. (Another challenge where padding and right-aligning a grid is the main component.) Mar 9, 2017 at 18:25
• @JonathanAllan I've changed the wording a bit. You can assume the smallest possible negative input is -99 and the largest possible positive input is 99. Mar 9, 2017 at 22:08
• Proposed test case: -3,15. Some answers don't work properly. Mar 10, 2017 at 5:52

Jelly, 2524 20 bytes

rµḊṖNµÐĿZbȷG€Ỵ€Zj€”,


Try it online!

How it works

rµḊṖNµÐĿZbȷG€Ỵ€Zj€”,  Dyadic link. Arguments: a, b

r                      Range; yield [a, ..., b].
µ   µÐĿ               Apply the enclosed chain until the results are no longer
unique. Return the array of results.
Ḋ                      Dequeue; remove the first item.
Ṗ                     Pop; remove the last item.
N                    Negate; multiply all remaining integers by -1.
Z               Zip; transpose rows and columns.
bȷ             Base 1000; map each n to [n].
G€           Grid each; in each row, pad all integers to the same length,
separating the (singleton) rows by linefeeds.
Ỵ€         Split each result at linefeeds.
Z        Zip to restore the original layout.
j€”,    Join each row, separating by commata.


05AB1E, 59 bytes

Once again I'm screwed over by the same bug I wrote a fix for months ago but never pushed...
Golfing should still be possible though.

Ÿ[Ðg1‹#ˆ¦(¨]\\¯vy€g}})J.Bvyð0:S})øvyZs\})U¯vyvyXNèyg-ú}',ý,


Try it online!

• I got pretty close with this: ŸÐ',ý,gÍ;µ¦¨(D',ý,¼, it doesn't quite fit the formatting specs, see if you can improve it ;)
– Okx
Mar 9, 2017 at 16:51
• @Okx: Yeah the formatting is definitely the tough part here. Something like Ÿ[Ðg1‹#',ý,¦(¨ would be enough otherwise :) Mar 9, 2017 at 16:57
• Doesn't work properly for inputs like -3,15. Mar 10, 2017 at 5:55
• @betseg: RIght you are. Reverted back to the old version. Mar 10, 2017 at 9:20

Java 8, 483480486† 467 bytes

(a,b)->{int f=0,l=b-a+3,z[][]=new int[l][l],y[]=new int[l],i,j,k=0;for(;b-a>=0;k++,a++,b--,f^=1)for(j=0,i=a;i<=b;i++)z[k][j++]=f<1?i:-i;String r="",s;for(i=0;i<l;y[i++]=k)for(j=0,k=1;j<l;k=f>k?f:k)f=(r+z[j++][i]).length();for(i=0;i<l;i++){k=z[i][0];if(i>0&&k==z[i][1]&k==z[i-1][2])break;for(j=0;j<l;){k=z[i][j];s="";for(f=(s+k).length();f++<y[j];s+=" ");f=z[i][++j];if(k==f){r+=(i>0&&z[i-1][1]==z[i][1]?s+0:"")+"\n";j=l;}else r+=s+k+(f==z[i][j+1]?"":",");}}return r;}


Bytes raised due to bug-fix..

Ok, this took A LOT more time (and bytes) than I thought (in Java that is..). This can definitely be golfed some more, probably by using a completely different approach instead of creating an NxN grid-array to fill and then 'strip out' the zeros (with an annoying edge case for the test-case of -1,1, as well as -12,12).

Try it online.

Explanation:

(a,b)->{        // Method with two integer parameters and String return-type
int f=0,      //  Flag-integer, starting at 0
l=b-a+3,  //  Size of the NxN matrix,
//  plus two additional zeros (so we won't go OutOfBounds)
z[][]=new int[l][l],
//  Integer-matrix (default filled with zeros)
y[] = new int[l],
//  Temp integer-array to store the largest length per column
i,j,k=0;  //  Index-integers
for(;b-a>=0   //  Loop as long as b-a is not negative yet
;         //    After every iteration:
k++,     //     Increase k by 1
a++,     //     Increase a by 1
b--,     //     Decrease b by 1
f^=1)    //     Toggle the flag-integer f (0→1 or 1→0)
for(j=0,i=a;i<=b;i++)
//   Inner loop i in the range [a, b]
z[k][j++]=//    Set all the values in the matrix to:
f<1?    //     If the flag is 0:
i      //      Simply use i
:       //     Else (flag is 1):
-i;    //      Use the negative form of i instead
String r="",  //  The return-String
s;     //  Temp-String used for the spaces
for(i=0;i<l;  //  Loop i over the rows of the matrix
;y[i++]=k)//    After every iteration: Set the max column-width
for(j=0,k=1;j<l;
//   Inner loop j over the cells of each row
k=f>k?f:k)
//     After every iteration: Set k to the highest of k and f
f=(r+z[j++][i]).length();
//    Determine current number's width
//    (NOTE: f is no longer the flag, so we re-use it as temp value)
for(i=0;i<l;i++){
//  Loop i over the rows of the matrix again
k=z[i][0];  //   Set k to the first number of this row
if(i>0      //   If this isn't the first row
&&k==z[i][1]&k==z[i-1][2])
//   and the first number of this row, second number of this row,
//   AND third number of the previous row all equal (all three are 0)
break;    //    Stop loop i
for(j=0;j<l;){
//   Inner loop j over the cells of each row
k=z[i][j];//    Set k to the number of the current cell
s="";     //    Make String s empty again
for(f=(s+k).length();f++<y[j];s+=" ");
//    Append the correct amount of spaces to s,
//    based on the maximum width of this column, and the current number
f=z[i][++j];
//    Go to the next cell, and set f to it's value
if(k==f){ //    If the current number k equals the next number f (both are 0)
r+=     //     Append result-String r with:
(i>0  //      If this isn't the first row
&&z[i-1][1]==z[i][1]?
//      and the second number of this and the previous rows
//      are the same (both are 0):
s+0 //       Append the appropriate amount of spaces and a '0'
:    //      Else:
"") //       Leave r the same
+"\n";//     And append a new-line
j=l;}  //     And then stop the inner loop j
else      //    Else:
r+=s     //     Append result-String r with the appropriate amount of spaces
+k    //     and the number
+(f==z[i][j+1]?"":",");}}
//     and a comma if it's not the last number of the row
return r;}    //  Return the result r


Javascript (ES6), 269 bytes

(a,b,d=~a+b+2,o=Array(~~(d/2)+1).fill([...Array(d)].map(_=>a++)).map((e,i)=>e.slice(i,-i||a.a)).map((e,i)=>i%2==0?e:e.map(e=>e*-1)))=>o.map(e=>e.map((e,i)=>' '.repeat(Math.max(...[...o.map(e=>e[i]).filter(e=>e!=a.a)].map(e=>[...e+''].length))-${e}.length)+e)).join   Explained: ( // begin arrow function a,b, // input d=~a+b+2, // distance from a to b o=Array(~~(d/2)+1) // create an outer array of // (distance divided by 2 // floored + 1) length .fill( // fill each outer element // with the following: [...Array(d)] // create inner array of the // distance length and // fill with undefined .map(_=>a++) // map each inner element // iterating from a to b ) .map( // map outer array (e,i)=>e.slice(i,-i||a.a) // remove n elements from each end // of the inner array corresponding // to the outer index with a special // case of changing 0 to undefined ) .map( // map outer array (e,i)=>i%2==0?e:e.map(e=>e*-1) // sign change the inner elements // in every other outer element ) )=> // arrow function return o // outer array .map( // map outer array e=>e.map( // map each inner array (e,i)=>' '.repeat( // repeat space character the // following amount: Math.max(... // spread the following array to // max arguments: [... // spread the following to an // array: o // outer array .map(e=>e[i]) // map returning each element of // the same inner index from the // outer array .filter(e=>e!=a.a) // remove undefined elements ] .map(e=>[...e+''].length) // map each element to the // length of the string ) // returns the max string // length of each column -${e}.length              // subtract the current
// element's string length
// from the max string length

)                               // returns the appropriate amount

)
).join
// join each element of outer
// array as string with newline


const f = (a,b,d=~a+b+2,o=Array(~~(d/2)+1).fill([...Array(d)].map(_=>a++)).map((e,i)=>e.slice(i,-i||a.a)).map((e,i)=>i%2==0?e:e.map(e=>e*-1)))=>o.map(e=>e.map((e,i)=>' '.repeat(Math.max(...[...o.map(e=>e[i]).filter(e=>e!=a.a)].map(e=>[...e+''].length))-{e}.length)+e)).join  console.log('Test Case: -1,1') console.log(f(-1,1)) console.log('Test Case: -3,6') console.log(f(-3,6)) console.log('Test Case: -2,8') console.log(f(-2,8)) console.log('Test Case: -15,8') console.log(f(-15,8)) console.log('Test Case: -3,15') console.log(f(-3,15)) console.log('Test Case: -12,12') console.log(f(-12,12)) • Can you add the new test cases? Mar 10, 2017 at 10:50 QBIC, 46 bytes ::[0,-1*a+b,2|[a,b|?d*q';]q=q*-1┘a=a+1┘b=b-1?  How it works: :: Read the negative and positive ints as a and b [0,-1*a+b,2| FOR(c = 0; c < range(a, b); c+=2) {} This creates the proper amount of lines. [a,b| For each line, loop from lower to upper ?d*q Print the current point in the range, accounting for the sign-switch '; And suppress newlines. The ' and  stops interpreting special QBIC commands. ] NEXT line q=q*-1┘ Between the lines, flip the sign-flipper a=a+1┘ Increase the lower bound b=b-1? Decrease the upper bound, print a newline The outermost FOR loop is auto-closed at EOF.  Fortunately, when printing a number, QBasic auto-adds the necessary padding. • Another case of finding the right language to do the job :) +1 Mar 10, 2017 at 19:06 • +1 Is there an online compiler for QBIC available? I'd like to see it in action for all the test cases (although I take your word it auto-aligns everything). First time I'm seeing QBIC, so two questions when I read your explanation: If I read it correctly q's default value starts at 1? Do all values in QBIC start at 1, or is there something I'm missing here? And what is the d / where does the d stand for? Or is d the current number in the loop and the ? simply a necessary delimited in the for-loop's code (instead of ? being the current number, which was how I initially read it)? Mar 10, 2017 at 19:21 • @KevinCruijssen No online interpreter yet, sorry. I'm working on one, but it is harder than you think to get QBasic 4.5 running in your browser :-). q starts at 1. All lowercase letters are number vars and the letters q-z are initialised to 1-10. And several commands auto-assign numbers in the order they are found in the code. d is indeed the iterator on the inner FOR-loop. For more details, see also the showcase - or this Mar 10, 2017 at 20:23 Perl 6, 146 bytes {_:=(($^a..$^b).List,{-«.[1..*-2]}...3>*).List;$/:=[map {"%{.max}s"},roundrobin($_)».chars];map {join ',',map {$^a.fmt:$^b},flat($_ Z$/)},$_}  Try it Produces a sequence of strings Expanded: { # bare block lambda with placeholder parameters ｢$a｣ and ｢$b｣ # generate the data$_ := (                 # bind to $_ so it isn't itemized # produce a sequence ($^a .. $^b ).List, # seed the sequence, and declare parameters { -«\ .[ 1 .. *-2 ] } # get all the values except the ends and negate ... # keep producing until 3 > * # the length of the produced list is less than 3 ).List; # turn the Seq into a List # generate the fmt arguments$/ := [                 # bind an array to ｢$/｣ so it isn't a Seq map { "%{ .max }s" }, # turn into a ｢.fmt｣ argument ("%2s") roundrobin($_)\     # turn the "matrix" 90 degrees
».chars             # get the string length of each number
];

# combine them together
map
{
join ',',
map
{ $^a.fmt:$^b }, # pad each value out
flat(
$_ Z$/         # zip the individual number and it's associated fmt
)
},
$_ # map over the data generated earlier }  PHP 7.1, 277 Bytes for([,$a,$b]=$argv,$c=count($r=range($a,$b))/2;$c-->0;$r=range(-$r[1],-$r[count($r)-2]))$y[]=array_map(strlen,$x[]=$r);for($i=0;$i<count($y[0]);$i++)$z[$i]=max(array_column($y,$i));foreach($x as$g){$o=[];foreach($g as$k=>$v)$o[]=sprintf("%$z[$k]d",$v);echo join(",",\$o)."\n";}


Online Interpreter

• Can you link an online interpreter? Mar 10, 2017 at 7:35
• @betseg Done and realize that my version had not worked correctly Mar 10, 2017 at 11:52
• oh gawd just using php on codegolf.se. HAVE ALL THE UPVOTES. Mar 10, 2017 at 19:25

C# console application 196 Bytes

static void p(int a,int b){string S="",d ="";int c=-1;for(int i=b;i >=a;i--){c=c==1?c=-1:c=1;for(int j = a;j<=i;j++){S=j!=a?",":S="";d=d+S+(j*c);}d+= "\r\n";a++;}Console.Write(d);Console.Read();}

• Welcome to PPCG! You can indent your code using 4 spaces (see my edit). In code golf, you need to have the shortest byte-count (the amount of bytes in your code) possible - that means shorter variable names, and removal of spaces. Also, you should put your byte-count in your header once finished. Mar 11, 2017 at 6:33

Javascript - 196185 176 bytes

function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}l.shift();l.pop()}return h}


I'm not really up to speed with some of the newer JS techniques so this could probably be golfed much more.

Simply creates a good old-fashioned HTML table with no width defined for the cells so the first row defaults to the width of each entry hense optimal spacing. It also (ab)uses HTML's "feature" of not requiring closing tags if a new opening tag comes along first.

<script>
function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}l.shift();l.pop()}return h}
document.write(f(-1,1))
</script>

<script>
function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}l.shift();l.pop()}return h}
document.write(f(-3,6))
</script>

<script>
function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}h+='</tr>';l.shift();l.pop()}return h}
document.write(f(-2,8))
</script>

<script>
function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}h+='</tr>';l.shift();l.pop()}return h}
document.write(f(-15,8))
</script>

<script>
function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}h+='</tr>';l.shift();l.pop()}return h}
document.write(f(-3,15))
</script>

<script>
function f(i,j){l=[];for(x=i;x<j+1;x++)l.push(x);h='<table>';while(l.length>0){h+='<tr>';for(x=0;x<l.length;x++){h+='<td align=right>'+l[x];l[x]*=-1}h+='</tr>';l.shift();l.pop()}return h}
document.write(f(-12,12))
</script>

Python 2 - 208 bytes

Try it online

d,u=input()
l=[x for x in range(d,u+1)]
M=map(lambda x:~9<x<21-u-u%2and 2or 3,l)
M[-1]-=1
M[-2]-=1
while len(l)>0:print','.join(map(lambda i:('%'+'%d'%M[i]+'d')%l[i],range(len(l))));l=map(lambda e:-e,l[1:-1])


Creates array of padding values and then use it to construct needed formated strings

Explanation:

d,u=input()
# create list of all values
l=[x for x in range(d,u+1)]
# create array of padding values
# by default, padding 2 used for numbers in [-9;9] and 3 for all other (limited with -99 and 99)
# but contracting list moves numbers larger that 9 under ones, that are <=9
# so upper limit of padding 2 is limited with 21-u-u%2
# (~9 == -10)
M=map(lambda x:~9<x<21-u-u%2and 2or 3,l)
# last two elements should have lower padding as there won't be any other numbers it their columns
M[-1]-=1
M[-2]-=1
while len(l)>0:
# create formatted string for every element in l
# join all strings with comma
print','.join(map(lambda i:('%'+'%d'%M[i]+'d')%l[i],range(len(l))))
# get slice without first and last element and change sigh
l=map(lambda e:-e,l[1:-1])

• Hi, welcome to PPCG! Unfortunately, it currently isn't correct. You've added the same margin to all numbers, as well as add spaces as delimiter. The challenge was to use a delimiter of your choosing (except whitespace), but more importantly: have the alignment based on the number with the largest width in that specific column. Please see the Important section of the challenge, as well as the test cases as example. You aren't the first one to do it incorrect, but currently it's not valid with the specified challenge. Feel free to delete, modify to comply to the rules, and undelete your answer Mar 17, 2017 at 7:49
• @KevinCruijssen Thank you for pointing this! I've updated my answer Mar 17, 2017 at 10:40
• That indeed looks a lot better! Only one small rule you forgot: "The output may also contain a delimiter of your own choice (except for whitespaces and new-lines): I.e. , and ; and | are all acceptable delimiters." Currently you use a space as delimiter. But the main difficulty of the width has indeed been tackled, so you're doing great so far! Only this small change, and then it should be done. :) Mar 17, 2017 at 10:46
• Perfect! +1 Good job correcting everything. And once again welcome to PPCG. (Btw, is the space here: %l[i], range` required?) Mar 17, 2017 at 12:17
• @KevinCruijssen I hope to stick around PPCG for awhile, it seems very interesting (nope, saved one more byte) Mar 17, 2017 at 12:22