La suma es siempre 15

36

Escriba un programa o función que tome una matriz de enteros no negativos como entrada y genere un conjunto de vectores / matrices con los elementos de la matriz de entrada en orden, divídalos de modo que cada vector sume hasta 15. Si la suma de los primeros N elementos no "golpean 15", entonces el número que hizo pasar 15 debe cortarse, y el resto será el primer elemento del siguiente vector. Esto continúa hasta llegar al final de la matriz de entrada. Si la suma del vector final es menor que 15, entonces se debe agregar un número al final para que la suma suba.

Creo que las reglas se entienden más fácilmente mirando los ejemplos:

Input: 3 7 5 10
Output:
3 7 5           <- Sum is 15
10 5            <- 5 is added to make the sum 15

Input: 2 4 5 9 2 3 5 0 2 4 5 0 3
Output:
2 4 5 4          <- Sum 15. 9 is split in two. 
5 2 3 5          <- The first 5 is the remainder of 9
0 2 4 5 0 3 1    <- The last number is added to make the sum 15

Input: 1 1 1            
Output:
1 1 1 12         <- The number 12 is added to make the sum 15

Input: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Output:
1 2 3 4 5
6 7 2           <- 2 is the first part of 8
6 9             <- 6 is the remainder of 8
10 5            <- 5 is first part of 11
6 9             <- 6 is remainder of 11. 9 is first part of 12
3 12            <- 3 is remainder of 12. 12 is first part of 13
1 14            <- 1 is remainder of 13. 14 is 14
15
15              <- 15 is first part of 16
1 14            <- 1 is remainder of 16. 14 is first part of 17
3 12            <- 3 is remainder of 17. 12 is added to make the sum 15

Input: 20 20
Output:
15
5 10           <- 5 is remainder from the first 20
10 5           <- 10 is remainder from second 20. 5 is added to make the sum = 15.

Tanto el formato de entrada como el de salida son opcionales. Lo que sea mejor en tu idioma.

El código más corto en bytes gana.


Tabla de clasificación

El Fragmento de pila al final de esta publicación genera el catálogo a partir de las respuestas a) como una lista de la solución más corta por idioma yb) como una tabla de clasificación general.

Para asegurarse de que su respuesta se muestre, comience con un título, usando la siguiente plantilla de Markdown:

## Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Si desea incluir varios números en su encabezado (por ejemplo, porque su puntaje es la suma de dos archivos o desea enumerar las penalizaciones de la bandera del intérprete por separado), asegúrese de que el puntaje real sea el último número en el encabezado:

## Perl, 43 + 2 (-p flag) = 45 bytes

También puede hacer que el nombre del idioma sea un enlace que luego aparecerá en el fragmento:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

Stewie Griffin
fuente
'El formato de salida es opcional'. ¿Eso significa [[3, 7, 5], [10, 5]]que sería una salida válida para el primer caso de prueba?
Morgan Thrapp
@MorganThrapp, sí. Eso es válido.
Stewie Griffin
1
@FlagAsSpam, agregué más explicaciones en el ejemplo que estás preguntando.
Stewie Griffin
3
Buen caso de prueba:Input: 100 Output: 15; 15; 15; 15; 15; 15; 10 5
randomra
3
Esto definitivamente debería reemplazar la prueba de FizzBuzz
CSᵠ

Respuestas:

8

Pyth, 37 bytes

K15VQ=+ZNIgZK=-ZK-NZbIZZ)).?N;I>KZ-KZ

Explicado

K15              Store 15 in K (the max) (K is Autoinitializing, no = needed here)
VQ              For N in the evaluated input
  =+ZN           Set Z(Which in pyth defaults to 0) to Z+N
  IgZK           If Z(row total) is greater than or equal to K (row max)
    =-ZK         Set Z to Z-K (How much the max was exceeded)
    -NZ          Implicitly print N-Z
    b            Implicitly print b (in pyth defaults to a newline)
    IZ         If Z > 0 (There was excess to carry to the next row)
      Z          Implicitly print Z (the excess)
  .?N            Else(the current row count is < the max(15)) output the current number
;                Use infinite )'s in place of )) (to save 1 character)
I>KZ             If K > Z (The max is greater than the current row count)
  -KZ           Implicitly print K-Z (The amount needed for the row to equal 15)

Este fue mi primer pitón, así que siéntase libre de sugerir mejoras.

Ejemplo:

Entrada

[1, 3, 4, 5, 9, 8]

Salida

1
3
4
5
2


7
8

Nota: ¡ Muchas gracias a Isaacg por varios bytes de consejos de reducción de tamaño y por crear Pyth en primer lugar! Por favor vota sus comentarios a continuación :)

csga5000
fuente
2
Else fue cambiado recientemente para ser en .?lugar de E, pero olvidé actualizar los documentos. Lo siento por eso.
isaacg
@isaacg Gracias isaacg! Debería tener eso funcionando ahora. Aunque solo ahorra 1 byte, ya que ahora tiene 2 caracteres.
csga5000
1
Fixing it as we speak.
isaacg
3
A couple of other suggestions: =Z+ZN and =+ZN are the same. It's a bit like Python's +=. Likewiese, =Z-ZK -> =-ZK. Also, you don't need the ) at the end - it's filled in automatically. Finally, FNQ and VQ are the same.
isaacg
1
You can save another 2 byte by replacing I>Z0 with IZ - Z can't be negative, so you're really just checking if Z is not zero, and zero is falsy, while all other numbers are truthy.
isaacg
16

Java - 229 200 192 181 172 170 168 bytes

Had already begun, not for the win but for the fun :)
Any suggestion is welcome.

Saved 8 bytes thanks to @ThomasKwa
Saved 20 bytes thanks to @corsiKa
Saved 2 bytes thanks to @Ypnypn
Saved 2 bytes thanks to @user902383

String p(int[]a){int c=0,j;String s="";f:for(int i:a){for(j=i;j-->0;)if(++c>14){s+=(i-j)+"\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}s+=i+" ";}return s+(15-c);}

170 bytes

String p(int[]a){int c=0,j;String s="";f:for(int i:a){for(j=i;j-->0;){if(++c>14){s+=(i-j)+"\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}}s+=i+" ";}return s+(15-c);}

172 bytes

String p(int[]a){int c=0,j;String s="";f:for(int i:a){for(j=i;j>0;){j--;if(++c>14){s+=(i-j)+"\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}}s+=i+" ";}return s+(15-c);}

181 bytes

void p(int[]a){int c=0,j;String s="";f:for(int i:a){for(j=i;j>0;){j--;if(++c>14){s+=(i-j)+"\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}}s+=i+" ";}System.out.print(s+(15-c));}

192 bytes

void p(int[]a){int c=0,j;String s="";f:for(int i:a){for(j=i;j>0;){j--;c++;if(c==15){s+=(i-j)+"\n";c=0;if(j>=15)continue;if(j>0)s+=j+" ";c+=j;continue f;}}s+=i+" ";}System.out.print(s+(15-c));}

200 bytes

void p(int[]a){int c=0,j;String s="";f:for(int i:a){j=i;while(j>0){j--;c++;if(c==15){s+=(i-j)+"\n";c=0;if(j>=15)continue;else{if(j!=0)s+=j+" ";c+=j;continue f;}}}s+=i+" ";}System.out.print(s+(15-c));}

229 bytes

void p(int[]a){int c=0,j;f:for(int i:a){j=i;while(j>0){j--;c++;if(c==15){System.out.print(i-j+"\n");c=0;if(j>=15){continue;}else{if(j!=0)System.out.print(j+" ");c+=j;continue f;}}}System.out.print(i+" ");}System.out.print(15-c);}

String p(int[] a) {
    int c = 0, j;
    String s = "";
    f: for (int i: a) {
        for (j = i; j-- > 0;)
            if (++c > 14) {
                s += (i - j) + "\n";
                c = 0;
                if (j < 15) {
                    if (j > 0) s += j + " ";
                    c += j;
                    continue f;
                }
            }
        s += i + " ";
    }
    return s + (15 - c);
}
Yassin Hajaj
fuente
1
Wow, hadn't seen continue actually used in a Java program until now.
Magic Octopus Urn
7

Python 3 - 1̶7̶7̶ 1̶3̶8̶ 1̶6̶6̶ 1̶3̶3̶ 113

s=0
i=15
p=print
for e in eval(input()):
 if s>=i:p()
 s=s%i+e
 if s>i:s-=i;p(e-s);p();e=s
 p(e)
if s!=i:p(i-s%i)

Edit 5 Truly golfed thanks to @poke *removed line breaks etc

Edit 4 Aliased print, and replaced a = with a -= to save a byte. Thanks to @poke and @elzell. Also moved input eval into for loop to save 2 bytes from assignment

Edit 3 Found savings in different OO inside second if

Edit 2 Fixed bug

Edit 1 Changed the input to be in the form '[1,2,3,4,5...]', and implemented first two comments, big thanks to @Morgan Thrapp

First time poster here. Input is command line with entries separated by spaces, output is entry per line, with a newline between groupings.

Adam Martin
fuente
3
You can get it down to 122 by assigning 15 to a variable and only using one space for indentation.
Morgan Thrapp
Also, you fail the second test case, I get 2 3 5, but it should be 5 2 3 5.
Morgan Thrapp
1
@AdamMartin You may be interested in my Pyth version of your code
csga5000
1
Since you’re using print so often, you should save it as a variable: p=print. Saves you another 14 characters.
poke
2
Current count is 132, but you can get it down to 113 if you remove some of the line breaks. You can combine every if into a single line, e.g. if s>i:s-=i;p(e-s);p();e=s for the second one. That saves you line breaks and indentation characters.
poke
7

Haskell, 126 107 102 100 bytes

[]#c=[]
(h:t)#c|s<0=t#u|s<1=u:t#[]|1<2=(c++[h-s]):(s:t)#[]where s=sum c+h-15;u=c++[h]
(#[]).(++[14])

Usage example: (#[]).(++[14]) $ [1..17] -> [[1,2,3,4,5],[6,7,2],[6,9],[10,5],[6,9],[3,12],[1,14],[15],[15],[1,14],[3,12]]

Edit: @Stewie Griffin helped me saving 19 bytes. Thanks!

nimi
fuente
4

CJam, 39 bytes

q~0af*Sf*N*30/{S-N/:,F1$:+-+0+e`W<e~p}/

Test it here.

This feels very suboptimal, but so far all my attempts at a shorter solution have been foiled by the presence of zeros in the input.

Martin Ender
fuente
4

Python2powered by RegEx: 158 155 bytes

Made in python with love and almost no math.
Or Regex Math if you will, unary math.
'Real' math used only to 'fix' the last requirement:

If the sum of the final vector is less than 15, then a number must be added at the end to make the sum go up.

Codegolfed:

import re
def f(i):o=[map(len,p.split())for p in re.findall('((?:x *){15}|.+)',' '.join(['x'*c for c in i]))];l=sum(o[-1]);o[-1]+=([],[15-l])[l<15];print o

The way this works is by converting each number N into a string of length N (x chosen as the char to fill up the string) and joining them all into a space separated string. Resulting string is split via RegEx BLACK MAGIC into something like:

['x xx xxx xxxx xxxxx ', 'xxxxxx xxxxxxx xx', 'xxxxxx xxxxxxxxx', 'x']

for an input like: f([1, 2, 3, 4, 5, 6, 7, 8, 10])
That's then split again, and the length of consecutive xes is used to create the numbers again, everything packed nicely in a list comprehension.

Ungolfed:

import re
o = [map(len, p.split()) for p in re.findall('((?:x *){15}|.+)', ' '.join(['x'*c for c in i]))]
l = sum(o[-1])
o[-1] += ([], [15-l])[l<15]
print o

Output:

>>> f([30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16])
[[15], [15], [1, 2, 3, 4, 5], [6, 7, 2], [6, 9], [15], [1, 14]]

Note: there wasn't enough magic for the 0s so this entry disqualifies

zeros must be included. See the second example

CSᵠ
fuente
All those function names are rather expensive. Makes using something like regex nearly impossible in code golf. Still, your byte size isn't bad considering
csga5000
4

Seriously, 88 bytes

,`'!*'0`M' j0╗`;;;'|ε35*('!=╜+;╗%(' =|('0=|I)`Mεj'|@s`ôl`╝`ö'0@s╛M`Md;Σ35*-;`X``@q`Iƒ@q.

Try it online

It's my first Seriously answer! Now I'm intimately familiar with all the language's shortcomings!

Hex Dump:

2c6027212a2730604d27206a30bb603b3b3b277cee33352a2827213dbd2b3bbb252827203d7c2827303d7c49
29604dee6a277c407360936c60bc609427304073be4d604d643be433352a2d3b60586060407160499f40712e

Explanation:

,`'!*'0`M' j         Replace all the numbers by "0"+"!"*n, separated by " "
0╗                   Initialize an accumulator in register 0
` ... `M             Map the string with the following function:
   ;;;'|ε                Put three extra copies of the character, a pipe, an empty string
   35*                   and a 15 on the stack.
   ('!=                  Move one copy of the character to the top and push 1 if it's a !
   ╜+                    Load the accumulator, add the 1 or 0 from the preceding test
   ;╗                    Make a copy, and save it back to register 0
   %                     Modulo the sum by 15
   (' =|                 Or the result with whether the dug-up character is " "
   ('0=|                 Or the result with whether the dug-up character is "0"
   I                     If we're at " " or "0" or the current sum is not divisible by 15,
                         push empty string, else push "|"
   )                     Bury the new character under the original character.
εj                   Join the list that resulted from the map into a single string.
'|@s                 Resplit the string on occurrences of "|" (after every 15 "!"s)
`ôl`╝                Store a function in register 1 which trims whitespace
                     and returns the length of the remaining string
` ... `M             Map the list with the following function:
   ö                     Trim leading spaces.
   '0@s                  Split the string on occurrence of "0"
   ╛M                    Map the resulting list with the function stored in register 1
d;                   Push the last sublist from the resulting list and make a copy.
Σ                    Find the sum of the list.
35*-                 Subtract it from 15
;`X``@q`Iƒ           Duplicate it, drop it if it's zero, put it in the list otherwise.
@q.                  Put the list back in the big list and print it.
quintopia
fuente
If Unicode code points are used, then do those characters count as 2 bytes each? :P
Dan
I'm using the unicode in the depicted source so that it can be read the way it is meant to look. Otherwise it would look like random garbage full of unprintables. The official source is the hex dump.
quintopia
It was meant to be a humorous question
Dan
1
It was also a reasonable question another reader might wonder about, so I answered it humorlessly.
quintopia
@quintopia +1 For trying a new golfing language! New languages are fun ;) I tried pyth for my first time on this question as well.
csga5000
3

Javascript, 138 128 bytes

i=>eval("for(o=z=n='',m=15,t=q=0;q<i.length;q++)(t+=c=+i[q])>=m?(t-=m,z+=c-t,o+=z+`\n`,z=t>0?t+' ':n):z+=c+' ';t<m?o+z+(m-t):o")

With whitespace:

i => eval("
  for(o=z=n='', m=15, t=q=0; q < i.length; q++)
    (t+=c=+i[q])>=m
      ?(
        t-=m,
        z+=c-t,
        o+=z+`\n`,
        z=t>0?t+' ':n)
      :
        z+=c+' '
    ;
  t<m ? o+z+(m-t) : o
")

Example:

Assign the function to a variable

sumFifteen=i=>eval("for(o=z=n='',m=15,t=q=0;q<i.length;q++)(t+=c=+i[q])>=m?(t-=m,z+=c-t,o+=z+`\n`,z=t>0?t+' ':n):z+=c+' ';t<m?o+z+(m-t):o")

Then evaluate like so:

console.log(sumFifteen([1,4,11,4,5]))

1 4 10
1 4 5 5

Revision history:

12/3/2015 00:02 - Thanks to user81655(+1 him in the comments) for 10 byte improvement

12/2/2015 21:44 - Switched to use functional style in-order to reduce size.

csga5000
fuente
3
You could improve this with these: f= is not needed according to site rules, remove the parentheses from (i), surround with eval so you don't need return or the brackets and replace the if with a ternary so that o is returned and change '\n' to `\n`, merge t+=... with t>=m to remove for loop brackets. Here's your solution in 127 bytes with all these improvements: i=>eval("for(o=z=n='',m=15,t=q=0;q<i.length;q++)(t+=c=+i[q])>=m?(t-=m,z+=c-t,o+=z+`\n`,z=t>0?t+' ':n):z+=c+' ';t<m?o+z+(m-t):o")
user81655
@user81655 I'll implement some of those changes! When I try yours I get a SytaxError: Unexpected token ILLEGAL(...). Note, in order to test function I added f=
csga5000
1
SO adds some symbols after o+ at the end of the line. Delete o+=z and write it again and it will work. :P
user81655
@user81655 I don't see how \n makes any difference
csga5000
1
You mean the `\n`? It won't work without it because the code is inside "..." because of the eval.
user81655
2

Python 3: 139 bytes

Slightly different approach than the other answer. Produces the actual output from the question because I initially assumed that was a requirement.

def f(l):
 m=15;r,s=sum(l)%m,0
 if r:l+=[m-r]
 while l:
  x=l.pop(0)
  if s+x>m:y=m-s;l[0:0]=[x-y];x=y
  s+=x;print(x,end=' \n'[s==m]);s%=m

Example usage:

>>> f([2, 4, 5, 9, 2, 3, 5, 0, 2, 4, 5, 0, 3])
2 4 5 4
5 2 3 5
0 2 4 5 0 3 1
poke
fuente
2

Perl, 86 bytes

#!perl -p
s|\d+( ?)|($i+=$&)<15?$&:($a=$&-($i%=15)).$/.($&>$a&&$&-$a.$1)|ge;$\=$".(15-$i)if$i

Counting the shebang as three, input is taken from stdin, space separated.


Sample Usage

$ echo -n 2 4 5 9 2 3 5 0 2 4 5 0 3 | perl sum15.pl
2 4 5 4
5 2 3 5
0 2 4 5 0 3 1
primo
fuente
2

R, 155 bytes

n=scan();while(S<-sum(n)){C=cumsum(n);if(S>14){w=which(C>14)[1];N=n[1:w];n=n[-(1:w)];r=C[w]-15;N[w]=N[w]-r;if(r)n=c(r,n);cat(N,"\n")}else{cat(n,15-S);n=0}}

With indents and linebreaks:

n=scan()
while(S<-sum(n)){
     C=cumsum(n)
     if(S>14){
         w=which(C>14)[1]
         N=n[1:w]
         n=n[-(1:w)]
         r=C[w]-15
         N[w]=N[w]-r
         if(r) n=c(r,n)
         cat(N,"\n")
         }else{
            cat(n,15-S)
             n=0
             }
      }

Usage:

> n=scan();while(S<-sum(n)){C=cumsum(n);if(S>14){w=which(C>14)[1];N=n[1:w];n=n[-(1:w)];r=C[w]-15;N[w]=N[w]-r;if(r)n=c(r,n);cat(N,"\n")}else{cat(n,15-S);n=0}}
1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
18: 
Read 17 items
1 2 3 4 5 
6 7 2 
6 9 
10 5 
6 9 
3 12 
1 14 
15 
15 
1 14 
3 12
> n=scan();while(S<-sum(n)){C=cumsum(n);if(S>14){w=which(C>14)[1];N=n[1:w];n=n[-(1:w)];r=C[w]-15;N[w]=N[w]-r;if(r)n=c(r,n);cat(N,"\n")}else{cat(n,15-S);n=0}}
1: 20 20
3: 
Read 2 items
15 
5 10 
10 5
> n=scan();while(S<-sum(n)){C=cumsum(n);if(S>14){w=which(C>14)[1];N=n[1:w];n=n[-(1:w)];r=C[w]-15;N[w]=N[w]-r;if(r)n=c(r,n);cat(N,"\n")}else{cat(n,15-S);n=0}}
1: 10 5
3: 
Read 2 items
10 5 
> n=scan();while(S<-sum(n)){C=cumsum(n);if(S>14){w=which(C>14)[1];N=n[1:w];n=n[-(1:w)];r=C[w]-15;N[w]=N[w]-r;if(r)n=c(r,n);cat(N,"\n")}else{cat(n,15-S);n=0}}
1: 2 4 5 9 2 3 5 0 2 4 5 0 3
14: 
Read 13 items
2 4 5 4 
5 2 3 5 
0 2 4 5 0 3 1
plannapus
fuente
2

Python 2, 117 bytes

i=input()
while i:
 s=15;r=[]
 while s>0:n=i.pop(0)if i else s;s-=n;r+=[n]if s>=0 else[n+s]
 if s<0:i=[-s]+i
 print r

Takes input as list:

>>[2,4,5,9,2,3,5,0,2,4,5,0,3]
[2, 4, 5, 4]
[5, 2, 3, 5]
[0, 2, 4, 5, 0, 3, 1]
TFeld
fuente
1

Perl, 76 bytes

Includes +3 for -p (normally +1, but +3 to play fair with the other perl solution)

Run with the input on STDIN (final newline on input is optional, but MUST be absent for the empty input)

sum15.pl <<< "1 2 3"

sum15.pl:

#!/usr/bin/perl -p
s/$/ 15/;s/\d+/1x$&/eg;s/( *1){15}\K ?/
/g;s/
1*
*$//;s/1+|\B/length$&/eg

Look ma, no calculations whatsoever...

Ton Hospel
fuente
Better late than never! Very nice solution though :)
Dada
0s are rather tricky in this solution (represented by extra spaces) and I have to be very careful to properly handle spaces to keep the number of 0s correct. In particular consider inputs where a partial sum is exactly 15, like 1 14 2 13. Try them without the ` ?` and see what happens
Ton Hospel
Yes, I tried it and saw that 0's where added at the begining of some lines like you say (that's why I deleted my comment 30 seconds after posting it). Thanks
Dada
0

Java - 158 155 bytes

Lambda version of https://codegolf.stackexchange.com/a/65590/46866 by yassin-hajaj, Not sure if a valid submission, but dont have enough rep to add a comment on the linked answer. Counted using http://meta.codegolf.stackexchange.com/questions/4944/byte-counter-snippet

a->{int c=0,j;String s="";f:for(int i:a){for(j=i;j-->0;)if(++c>14){s+=(i-j)+"\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}s+=i+" ";}return s+(15-c);}

158 Bytes

a->{int c=0,j;String s="";f:for(int i:a){for (j=i;j-->0;)if(++c>14){s+=(i-j)+ "\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}s+=i+ " ";}return s+(15-c);}

Ungolfed

a ->
    {
        int c=0, j;
        String s = "";
        f:
        for (int i : a) {
            for (j = i; j-- > 0; )
                if (++c > 14) {
                    s += (i - j) + "\n";
                    c = 0;
                    if (j < 15) {
                        if (j > 0) s += j + " ";
                        c += j;
                        continue f;
                    }
                }
            s += i + " ";
        }
        return s + (15 - c);
    }

can be used like

Function<int[], String> func =a->{int c=0,j;String s="";f:for(int i:a){for (j=i;j-->0;)if(++c>14){s+=(i-j)+ "\n";c=0;if(j<15){if(j>0)s+=j+" ";c+=j;continue f;}}s+=i+ " ";}return s+(15-c);};
System.out.println(func.apply(new int[]{2, 4, 5, 9, 2, 3, 5, 0, 2, 4, 5 ,0 ,3}));
The_Lone_Devil
fuente