La horda flotante

28

Introducción

La lluvia finalmente se calmó. La mayoría de la humanidad se ahogó debido a un error en el código de @ user12345 . Los sobrevivientes se encuentran dispersos en un archipiélago mundial. La comunicación por radio ha terminado y la humanidad está lista para prosperar una vez más. Sin ninguna razón, los piratas zombis se han reunido en el Primer Meridiano y están barriendo hacia el oeste. La horda lo devora todo.

Problema

Nuestro escenario del fin del mundo se puede describir con 5 enteros en una sola línea que representan un conjunto de comunidades insulares cooperantes. Se ordenan desde el oeste (entero más a la izquierda) hacia el este (entero más a la derecha).

Comenzando con la isla más al este, los isleños huyen en parejas a la siguiente isla más cercana. Curiosamente, por cada pareja que se embarca, solo uno de ellos sobrevive al viaje. Los isleños solo viajan en parejas. Poblaciones extrañas eligen a un único habitante para quedarse y proporcionar las últimas actualizaciones de radio sobre las travesuras de la horda de zombis piratas. Las poblaciones se niegan a viajar hasta que todas las islas al este de ellas hayan completado sus migraciones o hayan muerto. Cuando la población llega a la isla final más occidental, cesa el viaje.

El gerente de operaciones del fin del mundo necesita un programa que pueda generar los recuentos finales de población de cada aldea.

Entrada de ejemplo

3 8 6 0 2

Salida de ejemplo

8 1 0 1 0

Supuestos

  • La entrada se puede proporcionar a través de stdin, leer desde un archivo nombrado arbitrariamente o aceptar como argumento
  • Para cada isla, 0 <= población <= 1024
  • Las poblaciones nunca saltan una isla

¡La respuesta más corta gana!

Perno de lluvia
fuente
Cuando dices argumento, ¿te refieres a un argumento para una función o como un argumento de línea de comandos para el programa?
Aleksi Torhamo
@AleksiTorhamo Línea de comando arg, para que no cuente para su total.
Rainbolt
29
Me encanta esta historia del fin del mundo con múltiples preguntas.
mikhailcazi
re: "las poblaciones nunca se saltan una isla": su ejemplo muestra la población que mueve varias islas seguidas. ¿Hay otro significado que me estoy perdiendo?
Allen Gould
1
@AllenGould Las poblaciones efectivamente se movieron a través de varias islas, pero nunca se saltaron una. Si hubiera 32 personas en la isla de la extrema derecha, morirían como 16, 8, 4 y finalmente 2 llegarían a la isla más a la izquierda.
Rainbolt

Respuestas:

26

APL, 16 caracteres

{(1e9,4⍴2)⊤2⊥⍎⍵}

La entrada se proporciona como cadena a este bloque:

{(1e9,4⍴2)⊤2⊥⍵} "3 8 6 0 2"
8 1 0 1 0

o un char menos si la entrada se proporciona como argumento para este bloque:

{(1e9,4⍴2)⊤2⊥⍵} 3 8 6 0 2
8 1 0 1 0

Se basa en la idea de Ilmari Karonen en este comentario .

  • 2⊥⍵ realiza una conversión de base 2 de la entrada.
  • (1e9,4⍴2)⊤así convierte este número nuevamente en la base 2 (para los cuatro últimos dígitos) y la base 1e9 para el primero, que es suficiente para los rangos de entrada dados anteriormente. ( 1e9,4⍴2construye la lista 1e9 2 2 2 2)

Tenga en cuenta que la huida del oeste se realiza automáticamente mediante la conversión de base durante este proceso.

Howard
fuente
Esto es genial.
Gareth
77
APLdebería ser ilegal ...
Kiwy
1
@ Kiwy No entiendo tu comentario. ¿Por qué se debe declarar ilegal la APL? Siéntase libre de enviar su solución APL también.
Howard
44
@Kiwy: Esto es más que solo usar APL ... también es un enfoque muy inteligente para la solución, que se adapta perfectamente a un programa APL. ¡De esto se trata el golf!
Claudiu
13

GolfScript, 23 22 caracteres

~]{{.2/@+\2%}*]}4*' '*

Un enfoque iterativo. La matriz se repite varias veces y cada vez se transfiere un número de pares de derecha a izquierda. Prueba el ejemplo en línea .

Breve explicación del código:

~]       # convert input to an integer
{        # loop 4 times (enough for a 5-elements input)
  {      # inject this block into the array
    .    # duplicate (l r r)
    2/   # determine surviving people (l r r%2)
    @+\  # add to the left (l+r/2 r)
    2%   # determine remaining people (l+r/2 r%2)
  }*
  ]      # make array again of the results
}4*
' '*     # format output
Howard
fuente
1
+1, esto se acorta más que cualquier cosa que pueda encontrar. Ahora, si no fuera por esa molesta regla de "detenerse en la isla más occidental", ~]{2base}2*' '*sería el truco ...
Ilmari Karonen
@IlmariKaronen Elija el idioma correcto (consulte la solución APL ) y la regla molesta se vuelve correcta .
Howard
8

GolfScript (25 caracteres)

~]-1%{\.1&\2/@+}*]-1%' '*

Demostración en línea

Solución bastante sencilla: hay un enfoque más interesante que define el valor de salida para cada isla en función de los valores de entrada, pero no creo que pueda jugarse tan lejos como seguir el algoritmo de redistribución descrito en la pregunta.

Peter Taylor
fuente
7

Javascript / ES6 (69)

Jugando con operadores bit a bit:

  • x&=1 mantiene el bit más bajo (1 si es impar, 0 si es par)
  • x>>1 es la división por 2 para enteros
f=a=>{a=a.split(' ');for(i=5;--i;a[i]&=1)a[i-1]-=-(a[i]>>1);return a}

Versión sin ES6:

function f(a){a=a.split(' ');for(i=5;--i;a[i]&=1)a[i-1]-=-(a[i]>>1);return a}

Ejemplos:
f("3 8 6 0 2")devoluciones [8, 1, 0, 1, 0]
f("0 997 998 999 1000")devoluciones[935, 0, 1, 1, 0]

Michael M.
fuente
1
Vea los comentarios de Rusher en una de las respuestas de Python; la entrada debe ser una cadena que siga el formato dado en el ejemplo, no una lista.
Aleksi Torhamo
@AleksiTorhamo tiene razón. Permitir una lista separada por comas pondría su código en una clara ventaja sobre aquellos que siguieron el formato proporcionado en el ejemplo. En el futuro, intentaré aclarar que el formato proporcionado en el ejemplo es el formato. Lo siento por eso.
Rainbolt
OK, editado. ¿Debería unirse también la salida o el formato de matriz está bien?
Michael M.
Se me ocurrió más o menos lo mismo: f=a=>{a=a.split(' ');for(x=5;--x;a[x]&=1)a[x-1]-=-a[x]/2|0;return a}68 caracteres.
MT0
6

Python - 96 caracteres

Primera vez jugando al golf! Entrada de stdin.

n=map(int,raw_input().split())
x=4
while x:n[x-1]+=n[x]/2;n[x]%=2;x-=1
print' '.join(map(str,n))
Perno de lluvia
fuente
1
Puede reducirlo a 100 si comprime el tiempo en una línea usando punto y coma en lugar de líneas nuevas y sangría, y elimina el espacio directamente después de la impresión :)
Aleksi Torhamo
@AleksiTorhamo Gracias. También aprendí que la división de enteros en cualquier versión de Python que use requiere solo una barra oblicua, así que la
bajé a
1
Ah, cierto! También me di cuenta de que también puede omitir el ' 'de la división, reduciéndolo a 96 y superando las otras soluciones de python2.
Aleksi Torhamo
5

J (26 caracteres)

Aquí está mi solución en J: ((<.@-:@}.,0:)+{.,2|}.)^:_

   islands1 =: 3 8 6 0 2
   islands2 =: 3 8 6 3 2
   ((<.@-:@}.,0:)+{.,2|}.)^:_ islands1
8 1 0 1 0
   ((<.@-:@}.,0:)+{.,2|}.)^:_ islands2
9 0 0 0 0

Esta solución general debería funcionar con cualquier número de islas.

Thomas Baruchel
fuente
5

Rubí, 97 90 74 72

Versión en línea

Lo jugué un poco más, ya no invirtió la matriz ...

f=->i{i=i.split.map(&:to_i);(1..4).each{|n|i[-n-1]+=i[-n]/2;i[-n]%=2};i}
David Herrmann
fuente
No debe invertir la cadena antes de dividir sino después. De lo contrario, su solución puede arrojar resultados incorrectos para números de varios dígitos en la entrada.
Howard
Incluso consideré ambas "posibilidades", aunque no estaba al tanto de los números con más de un dígito ...: D ¡Gracias!
David Herrmann
4

C - 121 caracteres

La entrada se toma de stdin.

a[5];main(i){b(i=0,0);while(i++<5)printf("%i ",a[i-1]);}b(i,j){scanf("%i",&i);return j<5?i+=
b(i,j+1)/2,a[j]=j?i&1:i,i:0;}
Oberon
fuente
¿Está codificado para solo 5 islas?
Geobits
4

Python2 - 98 caracteres

Entrada de stdin.

s=[0]
for v in raw_input().split()[::-1]:s=[int(v)+s[0]/2,s[0]%2]+s[1:4]
print' '.join(map(str,s))

Python3 - 79 caracteres

Entrada de stdin.

s=[0]
for v in input().split()[::-1]:s=[int(v)+s[0]//2,s[0]%2]+s[1:4]
print(*s)
Aleksi Torhamo
fuente
4

Python 2, 85 80 bytes

b=1
for x in raw_input().split():b=2*b+int(x)
print b/16-2,' '.join(bin(b)[-4:])

X personas que comienzan en cualquier isla son equivalentes a X * 2 personas que comienzan una isla a la derecha. Este código convierte a todos en la configuración inicial a su equivalente en los isleños de extrema derecha, luego usa la representación binaria del resultado para determinar cuántas personas terminan en cada isla.

EDITAR: acortó el código inicializando ba 1 en lugar de 0, permitiendo el uso de en binlugar de una cadena de formato.

user2357112 es compatible con Monica
fuente
¡Usar la representación binaria es ingenioso! Lettercount.com le dio un 85. ¿Ha contado en exceso o es una mala herramienta para usar?
Rainbolt
@Rusher: Mi herramienta estaba usando finales de línea CRLF. Contando con terminaciones de línea Unix, es 85.
user2357112 es compatible con Monica
3

Pitón (101)

l=map(int,raw_input().split())
for i in range(4):l[3-i]+=l[4-i]/2;l[4-i]%=2
print' '.join(map(str,l))

Recorremos la lista de atrás hacia adelante y movemos las poblaciones según la especificación, luego imprimimos la lista. Aquí hay una prueba rápida:

>>> l=map(int,raw_input().split())
3 8 6 0 2
>>> for i in range(4):l[3-i]+=l[4-i]/2;l[4-i]%=2
... 
>>> print' '.join(map(str,l))
8 1 0 1 0
arshajii
fuente
Se bloqueó cuando se le proporcionó una entrada que sigue el formato proporcionado en el ejemplo.
Rainbolt
@Rusher Actualicé la respuesta para trabajar con el formato exacto utilizado en la pregunta.
arshajii
Otros pueden estar en desventaja si se permiten excepciones especiales para los codificadores de Python. Lo siento, y gracias por actualizar tu respuesta. Intentaré ser más claro en el futuro que la entrada de ejemplo es el formato requerido.
Rainbolt
2

Mathematica 105

Esto debería funcionar con cualquier número de islas.

f[w_,n_:1]:=
If[n==Length@w,w,
f[w~ReplacePart~{-n-> Mod[z=w[[-n]],2],-(n+1)->(w[[-(n+1)]]+ z~Quotient~2)},n+1]]

Ejemplos

5 islas

f[{3, 8, 6, 0, 2}]

{8, 1, 0, 1, 0}


25 islas

f[{145, 144, 144, 59, 35, 129, 109, 99, 200, 24, 219, 96, 12, 121, 75,20, 153, 124, 131, 178, 228, 120, 63, 207, 228}]

{270, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }

DavidC
fuente
Mi solución produce 270, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0para sus datos de prueba largos. Creo que he confirmado que estoy en lo correcto.
OldCurmudgeon
Extraño, dado cómo funciona. Mañana echaré un vistazo al caso.
DavidC
2

Java - 647 533 pero esperando algunos puntos de brownie para Java 8 Streams.

class I{int p;I e;I(int p,I e){this.p=p;this.e=e;}void x(){if(e!=null){int r=p&1;e.p+=(p-r)/2;p=r;}}public String toString(){return ""+p;}}Deque<I>B(String d){H<I>e=new H<>();return Arrays.stream(d.split(" ")).map(s->Integer.valueOf(s)).map(p->e.hold(new I(p,e.held()))).collect(Collectors.toCollection(LinkedList::new));}void x(Deque<I>is){is.descendingIterator().forEachRemaining((I i)->{i.x();});}void t(String s){Deque<I> a=B(s);x(a);System.out.println(a);}class H<T>{T h=null;H(){}T hold(T t){return (h=t);}T held(){return h;}}

La forma sin comprimir:

private static class Island {
  int population;
  final Island eastwardIsland;

  Island(int population, Island eastwardIsland) {
    this.population = population;
    this.eastwardIsland = eastwardIsland;
  }

  private void exodus() {
    if (eastwardIsland != null) {
      // How many remain.
      int remain = population & 1;
      // How many leave.
      int leave = population - remain;
      // Account for 50% death rate.
      int arrive = leave / 2;
      // Modify the eastward island population.
      eastwardIsland.population += arrive;
      // Change my population.
      population = remain;
    }
  }

  @Override
  public String toString() {
    return String.valueOf(population);
  }

}

private Deque<Island> buildIslands(String data) {
  // Holds the island to the east as we traverse.
  final Holder<Island> eastward = new Holder<>();
  // Build my list of islands - assumes order is retained.
  return Arrays.stream(data.split(" "))
          // Convert to int.
          .map(s -> Integer.valueOf(s))
          // Build the island in a chain.
          .map(p -> eastward.hold(new Island(p, eastward.held())))
          // Roll them into a linked list.
          .collect(Collectors.toCollection(LinkedList::new));
}

private void exodus(Deque<Island> islands) {
  // Walk backwards.
  islands.descendingIterator()
          // Perform all exodus.
          .forEachRemaining((Island i) -> {
            i.exodus();
          });
}

private void test(String data) {
  Deque<Island> archipelago = buildIslands(data);
  // Initiate the exodus.
  exodus(archipelago);
  // Print them.
  System.out.println(archipelago);
}

Con una asistencia de:

// Mutable final.
private static class Holder<T> {
  private T held = null;

  public Holder() {
  }

  public Holder(T it) {
    held = it;
  }

  public T hold(T it) {
    return (held = it);
  }

  public T held() {
    return held;
  }

  @Override
  public String toString() {
    return held == null ? "null" : held.toString();
  }

}

Ligeramente preocupado de que la prueba de @ DavidCarraher:

145 144 144 59 35 129 109 99 200 24 219 96 12 121 7520 153 124 131 178 228 120 63 207 228

genera

270, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0
OldCurmudgeon
fuente
2

Java - 196 195

Me dije a mí mismo que no lo publicaría si no podía obtenerlo por debajo de 200 ... Sinceramente, no creo que pueda deshacerme de nada más, es bastante delgado para Java.

class H{public static void main(String[]a){int l=a.length,p[]=new int[l],i=l;for(;i-->0;){p[i]=Integer.valueOf(a[i]);if(l-i>1){p[i]+=p[i+1]/2;p[i+1]%=2;}}for(;++i<l;System.out.print(p[i]+" "));}}

Saltos de línea:

class H{
    public static void main(String[]a){
        int l=a.length,p[]=new int[l],i=l;
        for(;i-->0;){
            p[i]=Integer.valueOf(a[i]);
            if(l-i>1){
                p[i]+=p[i+1]/2;
                p[i+1]%=2;
            }
        }
        for(;++i<l;System.out.print(p[i]+" "));
    }
}

Muestra de entrada y salida:

$ java H 3 8 6 0 2
8 1 0 1 0

$ java H 0 1 2 3 4 5 6 7 8 9 10
1 1 1 1 1 1 1 0 1 0 0

$java H 235 897 158 693
809 1 0 1
Geobits
fuente
2

Java - 179 caracteres

Comprimido:

class F{public static void main(String[] a){int l=0,x,s,i=a.length-1;String z="";for(;0<=i;i--){x=Integer.valueOf(a[i])+l;s=i>0?x%2:x;l=(x-x%2)/2;z=s+" "+z;}System.out.print(z);}}

Normal:

public class FloatingHorde {

    public static void main(String[] a) {
        int leave = 0;
        String outputStr = "";
        for (int i = a.length - 1; 0 <= i ; i--) {
            int x = Integer.valueOf(a[i]) + leave;
            int stays = i > 0 ? x % 2 : x;
            leave = (x - x % 2) / 2;
            outputStr = stays + " " + outputStr;
        }
        System.out.print(outputStr);
    }
}

Salida de muestra:

$ java F 3 8 6 0 2
8 1 0 1 0

$ java F 7 6 5 4 3
11 1 1 1 1
Hopper Hunter
fuente
0

Emacs Lisp 144 caracteres

No es pequeño, pero funciona.

(lambda (d)
   (setq x d)(while(cdr x)
           (setcar(cdr x)(+(/(-(car x)(%(car x)2))2)(cadr x)))
           (setcar x (-(car x)(*(/(car x)2)2)))
       (pop x))
   (reverse d))
Jordon Biondo
fuente
Puede agregar un encabezado como #Java - 123 caracteres
Rainbolt
0

awk - 44 caracteres

{for(i=NF;i>1;){n=int($i/2);$i%=2;$--i+=n}}1
laindir
fuente
-2

Java - 116 caracteres

Por ejemplo int[] i = {2, 33, 16, 5};(supongo que esos no se suman al recuento, ya que cada número puede variar) generaría23 0 0 1

for(int j = i.length-1; j > 0; j--) {       
    while(i[j] > 1) {
        i[j] -= 2;
        i[j-1]++;
    }       
}
for(int j = 0; j < i.length; j++) {     
    System.out.print(i[j] + " ");
}
Jochen Reinschlüssel
fuente
44
¿Puedes proporcionar un compilador que ejecute este código? Además, el formato y las posibles fuentes para la entrada se proporcionaron en la pregunta. Moldear la entrada a una matriz de Java le brinda una ventaja injusta sobre los demás.
Rainbolt