Enanos y Monedas

32

La situación:

Varios ( M) enanos han encontrado un cofre de duende con Nmonedas de oro y tienen que dividirlos. Debido a las antiguas reglas que rigen la asignación del botín a los piratas en orden de antigüedad, el enano más viejo debería obtener una moneda más que el siguiente enano más antiguo, y así sucesivamente, de modo que el enano más joven obtenga M-1menos monedas que el enano más viejo. Además, ningún enano tiene que lanzar ninguna moneda (es decir, no hay monedas negativas para ningún enano)

Ayuda a los enanos a dividir las monedas de esta manera, o diles que esto es imposible.

El código del ganador siempre debe responder correctamente (este desafío es determinista) y seguir las reglas generales del .

Entrada

Se le da un número entero N (3 ≤ N ≤ 1000) para el número de monedas y un número entero M (3 ≤ M ≤ N) para el número de enanos, separados por espacios.

Salida

Si es imposible dividir las monedas de la manera que los enanos quieren, imprima -1 (menos uno). De lo contrario, imprime el número de monedas que recibirá cada enano, del más antiguo al más joven. Separa los números con espacios.

Muestras :

entrada

3 3

salida

2 1 0

entrada

9 3

salida

4 3 2

entrada

7 3

salida

-1

entrada

6 4

salida

3 2 1 0
Thomas Mortell
fuente
44
Te perdiste un "pirata".
Rawling
66
relevante
Raystafarian
3
Buen descubrimiento, @Raystafarian. Tal vez cuando el profesor consigue un solucionador general de M enanos en lugar de sólo 3, él / ella va a reconocer que el usuario Crowdsourced la respuesta :) - especialmente si esa es solucionador en J.
ProgrammerDan
Tarea o no, es una buena pregunta para los pitufos.
Level River St

Respuestas:

18

J - 32 29 28 25

No más corto que otra solución J, pero y usa una idea diferente

(]{.[:i:-:@-.@]-%)/ ::_1:

La respuesta para la cantidad de monedas que obtiene el gnomo de mayor rango es simplemente N/M+(M-1)/2(si es un número entero), construimos lo negativo de esto -:@-.@]-%. Luego i:crea una matriz como esa 2 1 0 _1 _2para el argumento _2y tomamos M elementos de ella.

silbido
fuente
1
+1 para un uso brillante de i:. Puede guardar otros tres caracteres escribiendo en %lugar de [%]y usando en -.@]lugar de (1-]).
algorithmshark
@algorithmshark ¡Gracias compañero J entusiasta!
swish
1
No puedo hacer +1 ya que @swish parece estar con los gnomos que acabamos de robar. ;)
TheConstructor
11

J - 30 char

Muy divertido para el golf. Muchas cosas salieron bien.

((+/@s~i.[){ ::_1:s=.+/&i.&-)/

Explicación:

  • /- Tome los enteros separados por espacios como argumento y deslice la función entre ellos. Es decir, considere N el argumento izquierdo de la función entre paréntesis (...)y M el argumento correcto.

  • i.&-- Negate ( -) y luego tomar enteros ( i.). Normalmente, cuando haces algo como lo i.5haces 0 1 2 3 4. i.Sin embargo, cada vez que recibe un número negativo, invierte esa lista de salida. Entonces, por ejemplo i._5, dará 4 3 2 1 0.

  • s=.+/&- Realice la acción anterior en cada argumento ( &) y luego haga una tabla de suma ( +/) de estas matrices. Ahora tenemos una tabla donde cada fila es una posible distribución de monedas a M enanos, aunque tal vez no cuando hay N monedas. Finalmente, este verbo de creación de tablas es tan útil que lo llamaremos sy lo usaremos más tarde.

  • +/@s~- Ahora, usamos snuevamente, pero intercambiamos ( ~) el orden de los argumentos, de modo que transponemos la tabla. Esta es una forma de golf de tomar la suma de cada fila después de crear la tabla ( +/@), teniendo que ver con la forma en que J resume las listas multidimensionales.

  • i.[ - En esta lista de sumas, buscamos el argumento izquierdo del verbo, es decir, N. Si N es un elemento, obtenemos ese índice; de ​​lo contrario, obtenemos la longitud de la lista, que en particular es un índice no válido.

  • { ::_1:- Ahora intentamos usar el índice para extraer una fila de la tabla s. {arrojará un error de dominio si el índice no es válido, por lo que en ese caso detectaremos el error ( ::) y devolveremos -1 ( _1:). Esto maneja todo. Como usamos i.&-anteriormente, la distribución de monedas será en orden descendente, como se requería.

Uso:

   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 9 3
4 3 2
   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 7 3
_1
   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 6 4
3 2 1 0
   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 204 17
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4
Algoritmo de tiburón
fuente
La entrada 9 3debe volver 4 3 2, no -1. Parece que hay una transposición en su uso de ejemplo?
ProgramadorDan
@ProgrammerDan Gracias, no entendí eso. Escribí mal los ejemplos. 9 3da 4 3 2y 7 3da _1, como se esperaba.
algorithmshark
Vio la solución y hizo +1 apropiadamente: D. Debería mirar a J, parece ingenioso.
ProgramadorDan
7

R - 71 70 67 66 65 caracteres

s=scan();m=s[2];x=s[1]-sum(1:m);cat(if(x%%m|-m>x)-1 else x/m+m:1)

Sin golf:

s = scan()    # Reads N and M by stdin.
m = s[2]
x = s[1] - m*(m-1)/2
cat(if (x %% m | x < -m) -1 else x/m + m:1)

Solución:

Si M es el número de enanos, entonces la secuencia de oro pagado puede descomponerse en dos series singulares. Primero una serie que termina en cero: M-1, ..., 2, 1, 0 y una serie constante de c, c, ..., c. La suma de la primera serie es siempre M * (M-1) / 2. Entonces, si el resto (x = N - M * (M-1) / 2) podría dividirse sin residuo (módulo igual a 0), cada enano obtiene x / M más la parte de la serie decreciente.

Uso:

> s=scan()
1: 10 4
3: 
Read 2 items
> m=s[2]
> x = s[1] - m*(m-1)/2
> cat(if (x %% m || x<0) -1 else x/m + (m-1):0)
4 3 2 1
lambruscoAcido
fuente
-1, la pregunta requiere escribir un programa completo y no una función. Ver meta.codegolf.stackexchange.com/a/1146/8766
user80551
@ user80551 Tienes razón. Ahora corregí el fragmento: ahora toma la entrada separada por espacios; la salida tampoco muestra más el '[1]'.
lambruscoAcido
1
Puedes guardar otro personaje reemplazándolo m*(m+1)/2consum(1:m)
Brian Diggs
@Brian Thx, ¡modificaré mi código!
lambruscoAcido
4

PHP (187)

Es mi primer intento de jugar al golf, y sé que podría ser mejor, pero aún así :)

Golfizado:

<?php
$b=fgets(STDIN);list($c,$d)=explode(' ',$b);if((($d&1)AND($c%$d==0))OR($c%$d==$d/2)){for($e=floor($c/$d)+floor($d/2);$e>floor($c/$d)-round($d/2);$e--){echo"$e ";}}else{die('-1');}?>

Sin golf:

<?php
$a = fgets(STDIN);
list($coins, $dwarves) = explode(' ', $a);
if ((($dwarves & 1) AND ($coins % $dwarves == 0)) OR ($coins % $dwarves == $dwarves / 2)) {
    for (
        $i = floor($coins / $dwarves) + floor($dwarves / 2);
        $i > floor($coins / $dwarves) - round($dwarves / 2);
        $i--
    ) {
        echo "$i ";
    }
}
else { 
  die('-1');
}
?>

Ejecutar en un shell

Idea básica:

Las monedas se pueden separar por estas reglas, si una de estas es verdadera:

  1. Los enanos son números impares, y las monedas son divisibles por los enanos sin restos.
  2. Los enanos son números pares, y las monedas restantes después de dividir monedas / enanos es igual a la mitad del número de enanos

Si es así, tomamos como base las monedas promedio por enano (ACPD). Pero tenemos que comenzar desde lo más alto y la producción hasta llegar a lo más bajo. Así que hacemos un bucle con contador a partir de ACPD + la cuenta del resto de los enanos hacia el extremo superior, y continuamos hasta llegar a la ACPD, la cuenta del resto de los enanos hacia el extremo inferior.

Básicamente es lo mismo si los enanos son impares (es decir, 5 enanos: el del medio es 3 y en ambos extremos quedan 2), pero no si son pares, por eso confiamos en el piso Y en la ronda.

Problemas hasta ahora: funciona con un número de monedas demasiado bajo, lo que significa que algunos enanos serán golpeados y despojados de sus preciosas ganancias. Y esto es triste. O al menos si te gustan los enanos.

Solución :

  1. Piense en una forma de calcular la cantidad más baja de monedas para que el cálculo no termine con enanos en el polvo.
  2. Diseña enanos no tan codiciosos.

Solución más inteligente :

Las monedas son de metal. Haz que los enanos los derrita a todos, y luego lánzalos en una cantidad menor / mayor de monedas, para que sean divisibles en cualquier caso.

La solución más inteligente :

Roba su montaña, renómbrate a Smaug y quédatelo todo para ti. Después de todo, ¿por qué tienes que molestarte con enanos gruñones?

Puente norte
fuente
4

Python 3 (100)

Usando la misma idea que @Geobits pero conforme a los requisitos de entrada y salida.

n,m=map(int,input().split())
κ,ρ=divmod(n-m*(m-1)//2,m)
x=[-1]if ρ else range(κ,κ+m)[::-1]
print(*x)
Evpok
fuente
Gracias por el aviso. No noté la separación de espacio agregada a las necesidades de entrada.
Geobits
Esos pueden tener 100 caracteres, pero debido a los nombres de las variables griegas, requiere 105 bytes.
Jonathan Frech
4

Python 3 - 109 107 103 102 90 93

Usando la misma idea que Evpok, pero con una serie de mejoras.

n,m=map(int,input().split())
k=n/m+m/2
a=int(k)
print(*(range(a,a-m,-1),[-1])[k-a-.5or~a>-m])

Las mejoras son:

  1. Eliminando el espacio después de otra cosa y antes ''. 1 personaje
  2. Eliminar el '' dentro de split (), porque dividir en espacios es un valor predeterminado. 3 personajes
  3. Bajando x en 1 cambiando -1 a +1 dentro de divmod, y luego cambiando la función de rango para usar la opción de orden inverso del rango. 3 personajes
  4. EDITAR: ... si ... más ... cambió a ... y ... o ... 2 caracteres.
  5. EDITAR: Divmod hecho explícito, r eliminado. 4 personajes
  6. EDITAR: x eliminado, m // n usado explícitamente. 1 personaje
  7. EDITAR: utiliza expresiones destacadas en lugar de '' .join (map (str, ...)), agrega x para evitar repetir print (). 12 caracteres
  8. EDITAR: Me di cuenta de que estaba permitiendo que se dieran números negativos de monedas a los Enanos. Cambié el código para evitar esto.
isaacg
fuente
Bien hecho, fue instructivo :) Cambié mi respuesta para eliminar el espacio innecesario, pero tu truco para guardarlo [::-1]es mejor que mi solución. +1
Evpok
Puede que me falte algo, pero conté 93 bytes en lugar de 94.
Jonathan Frech
3

Python 3 - 114

n,m=map(int,input().split(' '))
r=range(m);n-=sum(r)
if n%m<1:
 for x in r:print(m-x+n//m-1,end=' ')
else:print -1

Funciona comprobando si N-(M*(M-1)/2)es divisible por M. Nuevo en python, por lo que cualquier consejo es apreciado.

Ejemplo de Ideone.com

Input:
735 30
Output:
39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10
Geobits
fuente
¿Hubo alguna vez una versión de Python 3 que admitiera el printestilo de declaración de Python 2 ? ¿O cómo la última línea ( else:print -1) no produce un error?
Jonathan Frech
3

C # - 322

using System;using System.Linq;namespace D{class P{static void Main(string[]args){int n=Convert.ToInt16(args[0]);int m=Convert.ToInt16(args[1]);bool b=false;int q=n/2+1;g:b=!b;int[]z=new int[m];for(int i=0;i<m;i++){z[i]=q-i;}if(z.Sum()==n)foreach(int p in z)Console.Write(p+" ");else{q--;if(b)goto g;Console.Write(-1);}}}}

Puntuación horrible pero tomé un enfoque diferente y pude usar goto:)

Lo acortaré más tarde.

Austin Henley
fuente
1
Definitivamente puede acortar todas esas Convert.ToInt16llamadas a solo int.Parse. Puede declarar cualquier variable preasignada con var(en lugar de, por ejemplo int[]). Sus parámetros de línea de comandos no necesitan ser llamados args. Y puede alias tipos de uso frecuente como using C = Console. También creo que para una solución tan larga, es mejor presentar el espacio entre líneas intacto en lugar de guardar solo un par de caracteres. Ah, y tampoco estoy muy seguro de por qué gotoes mejor que las alternativas aquí ...
Aaronaught 05 de
3

Java 210

class A { public static void main(String[] a){int d=Integer.parseInt(a[0]),c=Integer.parseInt(a[1]);if (2*c%d==0) for (int i=0;i<d;i++) System.out.print((((1+(2*c/d)-d)/2)+i)+" "); else System.out.print(-1);}}
usuario902383
fuente
2
Bienvenido a PPCG, veo que tiene mucho espacio en blanco que se puede eliminar.
user12205
Puede eliminar muchos más espacios para jugar golf su respuesta un poco más, por ejemplo, class A{public static void main(String[]a)es válida y le ahorra 3 caracteres. Después de cada uno if, y alrededor de cada uno for, elimine el espacio en blanco ... etc.
ProgrammerDan
Es una locura que la parte "vacío público estático principal (S") sea tan larga como la solución J completa :)
Robert Grant
3

R: 77 73 70 caracteres

a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))

Cree un vector que vaya de (M-1) a 0 y agregue 1 a cada número hasta que la suma ya no sea inferior a N. Si es superior, la salida -1 o la salida del vector.

Sangrado y un poco sin golf:

a=scan()   #Reads in stdin (by default numeric, space-separated)
r=a[2]:1-1 #Creates vector (M-1) to 0
while(sum(r)<a[1])r=r+1 #Increments all member of vector by 1 until sum is not inferior to N
cat( #Outputs to stdout
    `if`(sum(r)>a[1], -1, r) #If superior to N: impossible, returns -1
    )

Ejemplo de uso:

> a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))
1: 9 3
3: 
Read 2 items
4 3 2
> a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))
1: 7 3
3: 
Read 2 items
-1
> a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))
1: 204 17
3: 
Read 2 items
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4
plannapus
fuente
2

Julia, 45

f(n,m)=(x=n/m-m/2+1/2;x%1==0?[x+m-1:-1:x]:-1)
julia> f(6,4)'
1x4 Array{Float64,2}:
 3.0  2.0  1.0  0.0

Solo un poco de álgebra, me llevó mucho más tiempo del que debería.

gggg
fuente
2

JavaScript - 76

Observe que k + (k - 1) + ... + (k - (M - 1)) = M (k - (M - 1) / 2) Establecer esto igual a N da k = N / M + (M -1) / 2 por la cantidad más alta. Si esto es entero, entonces k% 1 == 0 y las cantidades que estamos buscando son k, k - 1, ..., k - (M - 1).

Probablemente podría haber escrito esto más corto en otro idioma, pero aún no había una solución JS, así que aquí está:

N=3;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Ejecutar en la consola.

Entrada de ejemplo:

N=3;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Salida:

3
2
1 

Entrada:

N=6;M=4;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Salida:

3
2
1
0

Entrada:

N=7;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Salida: -1

Lástima que console.log sea tan largo deletrear :) Desafortunadamente, declararlo l=console.log.bind(console)no lo hace más corto, y simplemente l=console.logno funciona.

Entrada:

"N=3;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)".length

Salida:

76
CompuChip
fuente
Puedes usarlo c=consoley c.log()acortarlo.
user2428118
2

Golfscript, 35

~:M.(*2/-.M%{;-1}{M/M+,-1%M<' '*}if

Cómo funciona

En el siguiente ejemplo, la entrada es 9 3.

          # STACK: "9 3"
~         # Interpret the input string.
          # STACK: 9 3
:M        # Store the top of the stack (number of dwarves) in variable `M'.
.         # Duplicate the top of the stack.
          # STACK: 9 3 3
(         # Decrement the top of the stack.
          # STACK: 9 3 2
*         # Multiply the topmost elements of the stack.
          # STACK: 9 6
2/        # Divide the top of the stack by `2'.
          # STACK: 9 3
          # So far, we've transformed `M' into `M*(M-1)/2', which is the minimum amount of
          # coins all dwarves together will get. This number comes from the fact that the
          # youngest dwarf will get at least 0 coins, the next at least 1 coin, etc., and
          # 0 + 1 + ... + (M - 1) = M*(M-1)/2.
-         # Subtract the topmost elements of the stack.
          # STACK: 6
          # The remaining coins have to get reparted evenly to all dwarves.
.         # Duplicate the top of the stack.
          # STACK: 6 6
M%        # Calculate the top of the stack modulus `M'.
          # STACK: 6 0
{         # If the modulus is positive, the remaining coins cannot get reparted evenly.
    ;-1   # Replace the top of the stack by `-1'.
}
{         # If the modulus is zero, the remaining coins can get reparted evenly.
    M/    # Divide the top of the stack by `M'.
          # STACK: 2
          # This is the number of coins all dwarves will get after giving 1 to the second
          # youngest, etc.
    M+    # Add `M' to the top of the stack.
          # STACK: 5
    ,     # Replace the top of the stack by an array of that many elements.
          # STACK: [ 0 1 2 3 4 ]
          # The rightmost element is the number of coins the oldest dwarf will get.
    -1%   # Reverse the array.
          # STACK: [ 4 3 2 1 0 ]
    M<    # Keep the leftmost `M' elements.
          # STACK: [ 4 3 2 ]
          # There are only `M' dwarves.
    ' '*  # Join the array, separating by spaces.
          # STACK: "4 3 2"
}if
Dennis
fuente
1

Delphi XE3 (176)

uses SysUtils;var d,c,i:integer;begin read(c,d);for I:=1to d-1do c:=c-i;if c mod d>0then writeln(-1)else begin c:=c div d;for I:=d-1downto 0do write(IntToStr(i+c)+' ');end;end.

Cómo funciona.

Lee 2 enteros, monedas y enanos.
Resta la diferencia por enano.
Si el resto mod enanos> 0 es imposible.
De lo contrario, obtenga la misma participación por enano en un bucle de enanos-1 a 0 e imprime dwarfIndex + igual participación

Sin golf

uses SysUtils;
var
  d,c,i:integer;
begin
  read(c,d);
  for I:=1to d-1do
    c:=c-i;
  if c mod d>0then
    writeln(-1)
  else
  begin
    c:=c div d;
    for I:=d-1downto 0do
      write(IntToStr(i+c)+' ');
  end;
end.
Teun Pronk
fuente
1

Mathematica 65

La función, ggenera todas las secuencias de aumento por uno, de longitud m, de 0 a n y comprueba si alguna de ellas suma m. Si tiene éxito, se devuelve la secuencia; de lo contrario, se devuelve -1.

Las secuencias se realizan Partitionincorporando la lista {0,1,2,3 ... m} en todas las sublistas posibles de n enteros contiguos.

Por supuesto, hay formas más eficientes de lograr el mismo efecto, pero las que he encontrado requieren más código.

n_~g~m_:=If[(s=Select[Partition[0~Range~n,m,1],Tr@#==n&])=={},-1,s]

Ejemplos

g[9, 3]

{{2, 3, 4}}


g[3, 3]

{{0, 1, 2}}


g[7, 3]

-1


g[705, 3]

{{234, 235, 236}}


g[840, 16]

{{45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60}}


g[839, 16]

-1

DavidC
fuente
1

C 131

#include <edk.h>
main(int a,char **v){int j=atoi(*++v),k=atoi(*++v)-j*(j-1)/2;k<0||k%j?j=1,k=-1:k/=j;while(j--)printf("%d ",k+j);}

Sin golf

#include <edk.h> //Shortest standard header including stdio.h and stdlib.h
main(int a,char **v)
{
    int j=atoi(*++v),k=atoi(*++v)-j*(j-1)/2;

    k<0||k%j?j=1,k=-1:k/=j;  // If youngest dwarf gets < 0 or amount not equally divisible then set values such that ...

    while(j--)printf("%d ",k+j); // ... loop prints out correct values
}

Esto se compila con una advertencia porque main no tiene tipo. Si esto no es válido en las reglas del golf, tendría que agregar cinco caracteres.

Alquimista
fuente
1

Cobra - 198

Sitio web de Cobra

class P
    def main
        x,y=Console.readLine.split
        a,b=x to int,y to int
        l=[]
        t=n=0
        for i in b,t+=i
        while (t+=b)<=a,n+=1
        for i in b,l.insert(0,i+n)
        print if(t-b<>a,-1,l.join(" "))

Explicado:

class P
    def main

Requerido para que se ejecute el código

        x,y=Console.readLine.split
        a,b=x to int,y to int

Toma datos y los almacena como ayb

        l=[]
        t=n=0

Inicializa la lista de salida le inicializa el dinero total requerido ty el número de monedas para agregar a cada pila de enanosn

        for i in b,t+=i

Encuentra el valor monetario más bajo posible que dará como resultado que todos los enanos tengan un número permitido de monedas en su pila

        while (t+=b)<=a,n+=1

Determina cuántas monedas agregar a cada pila para que el dinero total requerido sea> = al dinero total disponible

        for i in b,l.insert(0,i+n)

Llena la lista con montones de dinero de diferentes tamaños.

        print if(t-b<>a,-1,l.join(" "))

Salidas -1o ldependiendo de si el dinero total requerido es igual al dinero total disponible

Οurous
fuente
-1

Python ( 100 96 94):

Una buena respuesta de puntaje redondo. Ya no más, pero ahora es más corto.

def f(n,m):a=range(m)[::-1];b=n-sum(a);c=b/m;d=[i+c for i in a];return(d,-1)[-1in d or c*m!=b]

Sin golf:

def f(n,m):
 a = range(m)[::-1]
 b = sum(a)
 c = (n-b)/m
 if c * m != n-b: return -1
 d = [i+c for i in a]
 return (d,-1)[-1 in d or c!=n-b]
 if -d in d or c*m!=n-b:
  return -1
 return d

Salida:

def f(n,m):a=range(m)[::-1];b=sum(a);c=(n-b)/m;d=[i+c for i in a];return (d,-1)[-1 in d or c*m!=n-b]

f(3,3)
Out[2]: [2, 1, 0]

f(9,3)
Out[3]: [4, 3, 2]

f(7,3)
Out[4]: -1

f(6,4)
Out[5]: [3, 2, 1, 0]
ɐɔıʇǝɥʇuʎs
fuente
2
Esto no sigue el requisito de entrada.
Austin Henley
-1, la pregunta requiere escribir un programa completo y no una función. Ver meta.codegolf.stackexchange.com/a/1146/8766
user80551