5
\$\begingroup\$

This challenge consist in adding commas to numbers every 3 spaces like:

123456789 => 123,456,789

Specifications:

  • The possible inputs will be 1,000 <= input <= 100,000,000
  • You can ONLY use Mathematical Operators
  • (*) You can NOT do string, array, index or character manipulation
  • You can NOT use any kind of built-in functions that add these commas
  • The zeros should remain, ex 10000 => 10,000
  • You need to print/alert/log the output (so "the output is at x var" is not allowed)

(*) the only exception is when forming/printing the output (but not in a manner that suggest cheating)

Examples

10100 => 10,100
120406 => 120,406
999999999 => 999,999,999

A basic idea on how to get numbers legally:

n = 123456;
m = roundDown(n / 10);//even if ends with .9
d = n - m;//we get the last number
\$\endgroup\$
4
  • \$\begingroup\$ Just to clarify, is 123,45,6 acceptable output for the input 123045006, or do we need to include the leading zeros? I'd assume we do, but if not, I have a very nice 13-char GolfScript solution. :) \$\endgroup\$ Mar 15, 2012 at 1:42
  • \$\begingroup\$ @IlmariKaronen we need to use the zeros. I will clarify that (updating) \$\endgroup\$
    – ajax333221
    Mar 15, 2012 at 4:23
  • \$\begingroup\$ Integers only or will it have to support floats too? \$\endgroup\$
    – elssar
    Mar 15, 2012 at 15:06
  • \$\begingroup\$ @elssar you can use floats as long as they don't add the commas for you automatically or something like that \$\endgroup\$
    – ajax333221
    Mar 15, 2012 at 15:26

13 Answers 13

6
\$\begingroup\$

You weren't very specific on the output format...

Haskell, 56

reverse.takeWhile(>0).map(`mod`1000).iterate(`div`1000)

example:

GHCi> reverse.takeWhile(>0).map(`mod`1000).iterate(`div`1000)$93842390862398
[93,842,390,862,398]
\$\endgroup\$
2
  • \$\begingroup\$ I don't understand Haskell, but is that array-free? \$\endgroup\$
    – ajax333221
    Mar 15, 2012 at 19:15
  • \$\begingroup\$ As array-free as it gets. Only lazy lists, i.e. pointers to functions and to integers. – It also has the leading-zero-problem, though, that requirement came in after my post; I can't fix that without String objects. Or can I? Wait... \$\endgroup\$ Mar 15, 2012 at 19:59
5
\$\begingroup\$

GolfScript, 13 37 chars

0:|;~{.10%|):|3%''','if@10/.9>}do]-1%

Look, Ma, no arrays!

Well, almost. The pieces of the output are collected on the stack in right-to-left order, so the final ]-1% is needed to reverse them. But I assume that's OK, as it counts as "forming/printing the output".

Here's an ungolfed version with comments:

0 :| ;         # initialize the variable | to the value 0
~              # eval the input, turning it from a string into a number

{              # start of loop
  .            # duplicate the number on top of the stack; we'll need it later
  10 %         # take the remainder modulo 10 and leave it on the stack

  | ) :| 3 %   # increment | by one and take the remainder modulo 3 of the result
  '' ',' if    # if the remainder is 0, push a comma onto the stack, else an empty string

  @            # pull the value we saved at the start of the loop to top of the stack
  10 /         # divide it by ten, rounding down
  . 9 >        # check if the result is greater than 9...
} do           # ...and repeat the loop if so

]              # finally, collect the digits and commas off the stack into an array...
-1 %           # ...and reverse it for output

If it weren't for a few pesky details, the following 13-char solution would be pretty hard to beat:

~1000base','*

However, it fails on two counts: it doesn't correctly preserve leading zeros in digit groups, and the built-in base conversion operator base might be considered "array manipulation", since it takes a number and returns an array of digits.


Ps. Here's an older 49-char arrayless solution:

~{.999>}{:^1000%:&9&>99&>+{0}*','^1000/}while]-1%
\$\endgroup\$
2
  • \$\begingroup\$ you used an array. Using strings, character position, indexes or arrays is not allowed \$\endgroup\$
    – ajax333221
    Mar 15, 2012 at 4:27
  • \$\begingroup\$ the only exception is when forming/printing the output, the "collect digits and commas" is a formatting operation; no cheating to me. I'm developing a C interpreter of a language derived from GolfScript, which is able to interpret this solution; if you remove the array-related ]-1% part,my lang will output the correct result since it by default "dumps" the stack from top to bottom (it seems to me more natural for a stack oriented lang);the point is that the result is ready, you need just formatting, and this must be allowed or very few solutions would be possible! \$\endgroup\$ Apr 29, 2012 at 15:55
3
\$\begingroup\$

awk, 47 chars

awk '{for(_=NF-2;1<_;_-=3)$_=","$_}NR' FS= OFS=
10,100
120,406
999,999,999
\$\endgroup\$
2
\$\begingroup\$

Python 2, 86 chars

I figured this warranted a different enough answer. The first answer is for 3.0 only because of the print statement with end=, and this answer because division automatically floors instead of converts to float, and the use of backticks

b=input()
k=0
x=''
while b>0:
 x=`b%10`+x;b/=10;k+=1
 if k%3==0and b>0:x=','+x
print x

Only string manipulation is building the output

edit: by adding 5 characters int(), this program can accept any integer, even above 1 billion. The previous program inserts Ls (python longs) if the number is too large, but is still within the constraints of the challenge. Here is the program that works with any integer:

b=input()
k=0
x=''
while b>0:
 x=`int(b%10)`+x;b/=10;k+=1
 if k%3==0and b>0:x=','+x
print x

-

879612587634598623589762354009
879,612,587,634,598,623,589,762,354,009
\$\endgroup\$
2
\$\begingroup\$

AWK, no strings, 84 chars:

{for(p=$0;.1<p/=10;++i);for(;i-->0;printf i&&i%3==0?"%d,":"%d",$0/10**i%10);print""}

Test runs:

% awk -f commas.awk <<< 1230
1,230
% awk -f commas.awk <<< 123012
123,012
% awk -f commas.awk <<< 12301 
12,301
% awk -f commas.awk <<< 12301000
12,301,000
\$\endgroup\$
2
\$\begingroup\$

C, 136

i,j,k;main(m,n){scanf("%d",&n);for(m=n;n^0;i++,n/=10);k=i%3;while(j++<i)printf("%d%c",(int)(m/pow(10,i-j))%10,j%3==k?',':0);putchar(8);}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'm curious, why do you say ;n^0; instead of just ;n;? \$\endgroup\$ Oct 1, 2014 at 3:56
  • \$\begingroup\$ In C, the ^ operator means xor, so it should evaluate to 0. In this case, with that context, the for loop should never run. Is this a typo? \$\endgroup\$
    – BrainSteel
    Oct 9, 2014 at 23:49
1
\$\begingroup\$

Python, 82 chars

n=input()
x=''
while n>999:x=','+`n/100%10`+`n/10%10`+`n%10`+x;n/=1000
print `n`+x

I can get it shorter (67 chars) with

while n>999:x=',%03d'%(n%1000)+x;n/=1000

Not sure if that's legal.

\$\endgroup\$
1
\$\begingroup\$

befunge, 62

&# <v%3-\3%3y+8a$j*d`0:/a\%a:
1`j@>:3%\3/!3*j',,\'0+,1+a8+y

well this code is array free, since befunge itself is array free.

  • the first line simply reads a number and push every digit into stack.
  • the second line reads those digits and prints then once at a time. and put commas if needed.

note that if you are trying to run it using rcfunge, you need run using "-Y" option.

\$\endgroup\$
1
\$\begingroup\$

Scala 65:

def f(n:Int){if(n<1000)print(n)else{f(n/1000)
print("."+n%1000)}}

Testcode:

val l=List(1,12,123,1234,12345,123456,1234567)
l.foreach(x=>{f(x);println})
\$\endgroup\$
0
\$\begingroup\$

Python 3, 165 chars

from math import*
b=int(input())
j=10**8
k=l=0
while j>0:
 z=int(floor(b/j));b-=z*j;k+=1;j=floor(j/10)
 if not l:l=z!=0
 if l:print(z,end=','if k%3==0and j>0 else'')

No strings except for '' and ',', no arrays/lists/tuples/dicts, or indexing

edit: nixxed some characters

\$\endgroup\$
3
  • \$\begingroup\$ Not sure how python works, but surely int(floor(x)) is the same as int(x) or floor(x)? And if python is anything like the languages I use, you should be able to change ','if k%3==0and j>0 else'' to ''if k%3&j>0 else',' Also, I think while j>0 can be changed to while j \$\endgroup\$
    – Griffin
    Mar 16, 2012 at 19:04
  • \$\begingroup\$ @Griffin thought int() rounded to the nearest. I guess I'm still learning some small details about Python xD. python's & operator is bitwise, not logical, so it can't be used the same way all the time. the while thing was just me being a noob \$\endgroup\$
    – Blazer
    Mar 16, 2012 at 20:48
  • \$\begingroup\$ floor is essentially truncating after the decimal point, depending on the language int will round or truncate. Either way doing int(floor()) is no different from floor(). In javascript, because of the loose typing ORing by zero will truncate decimals: AAA.BBB | 0 == AAA - this might work for phython... My bad about the bitwise and, at least switch the if statement around so you don't need the ==0 \$\endgroup\$
    – Griffin
    Mar 16, 2012 at 21:33
0
\$\begingroup\$

Python 2.6.5, 65 94 chars

n=input()
s=''
while n:
    s=','+str(x)+s if x else','+'000'+s
    n/=1000
print s[1:]

Just used the string to store the output.

*Now preserves zeros

\$\endgroup\$
2
  • \$\begingroup\$ does not preserve zeros. eg: 976235004 = 976,235,4 \$\endgroup\$
    – Blazer
    Mar 16, 2012 at 17:44
  • \$\begingroup\$ gah! back to the drawing board. \$\endgroup\$
    – elssar
    Mar 17, 2012 at 4:52
0
\$\begingroup\$

C, 80 chars

Using recursion within printf to reverse the printing order (recursion handles the least significant digits first, but printing is done when returning, so they're printed last).

n;
p(x) {
    x=n%1000;
    n/=1000;
    printf(n?p(),",%03d":"%d",x);
}
main(){
    p(scanf("%d",&n));
}
\$\endgroup\$
2
  • \$\begingroup\$ You can shave off a few characters if you declare something like v=1000 and use x=n%v; and n/=v. \$\endgroup\$
    – Mr. Llama
    Apr 30, 2012 at 16:15
  • \$\begingroup\$ @GigaWatt ,v=1000 costs 7 chars, saves 6. ,v=1e3 comes out even. \$\endgroup\$
    – ugoren
    Apr 30, 2012 at 17:22
0
\$\begingroup\$

JavaScript 104, 99, 90, 81

Edit: I just noticed I also have this missing zeros bug when any group of contains 000 ,00X or 0X0. If you see this message, the code below isn't fixed yet

Code:

for(n=0,s="",i=m=1e3,r=0;i<n*m;i*=m)r=~~((n%i-r)/i*m),s=r+(i-m?",":"")+s;alert(s)

Note: change the value of n for different inputs

\$\endgroup\$
3
  • \$\begingroup\$ ah, I just noticed I also have this missing zeros bug when any group of contains like 000 ,001 or 010... I will try to fix this later \$\endgroup\$
    – ajax333221
    Mar 15, 2012 at 15:44
  • \$\begingroup\$ I think the input should always count towards the final character count. at least the minimum: n=0; = 4 characters. I could reduce at least 6 characters in both my codes if input lines were free \$\endgroup\$
    – Blazer
    Mar 15, 2012 at 18:40
  • \$\begingroup\$ @Blazer maybe you are right, I will update that. Sorry, this is my second code-golf :) \$\endgroup\$
    – ajax333221
    Mar 15, 2012 at 19:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.