A Horda Flutuante

28

Introdução

A chuva finalmente diminuiu. A maior parte da humanidade se afogou devido a um erro no código do @ user12345 . Os sobreviventes estão espalhados por um arquipélago mundial. A comunicação via rádio está ativa e a humanidade está pronta para prosperar mais uma vez. Por nenhuma razão, piratas zumbis se reuniram no Meridiano Prime e estão se aproximando do oeste. A horda devora tudo.

Problema

Nosso cenário do dia do juízo final pode ser descrito por 5 números inteiros em uma única linha, que representam um conjunto de comunidades insulares cooperantes. Eles são ordenados de oeste (número inteiro mais à esquerda) a leste (número inteiro mais à direita).

Começando com a ilha mais a leste, os ilhéus fogem em pares para a próxima ilha mais próxima. Curiosamente, para cada par que embarca, apenas um deles sobrevive à viagem. Os ilhéus viajam apenas em pares. Populações ímpares elegem um único habitante para ficar para trás e fornecer as atualizações de rádio mais recentes sobre as travessuras da horda de piratas zumbis. As populações se recusam a viajar até que todas as ilhas ao leste delas concluam suas migrações ou morram. Quando a população chega à ilha final, mais a oeste, a viagem cessa.

O gerente de operações no fim do mundo precisa de um programa que possa gerar as contagens finais da população de cada aldeia.

Exemplo de entrada

3 8 6 0 2

Saída de exemplo

8 1 0 1 0

Suposições

  • A entrada pode ser fornecida via stdin, lida a partir de um arquivo nomeado arbitrariamente ou aceita como argumento
  • Para cada ilha, 0 <= população <= 1024
  • As populações nunca pulam uma ilha

A resposta mais curta vence!

Rainbolt
fonte
Quando você diz argumento, você quer dizer como argumento para uma função ou como argumento da linha de comando para o programa?
Aleksi Torhamo 10/03/2014
@AleksiTorhamo arg da linha de comando, para que não conte para o total.
Rainbolt
29
Eu amo essa história do dia do juízo final com várias perguntas.
Mikhailcazi
re: "populações nunca pulam uma ilha" - seu exemplo mostra a população movendo várias ilhas seguidas. Há outro significado que estou perdendo?
Allen Gould
1
@AllenGould As populações realmente se moveram por várias ilhas, mas nunca pularam uma. Se houvesse 32 pessoas na ilha da extrema direita, elas morreriam como 16, 8, 4 e, finalmente, 2 chegariam à ilha mais à esquerda.
Rainbolt

Respostas:

26

APL, 16 caracteres

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

A entrada é fornecida como sequência para este bloco:

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

ou um caractere a menos se a entrada for fornecida como argumento para este bloco:

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

É baseado na idéia de Ilmari Karonen neste comentário .

  • 2⊥⍵ faz uma conversão base 2 da entrada.
  • (1e9,4⍴2)⊤assim, converte esse número novamente na base 2 (para os quatro últimos dígitos) e na base 1e9 para o primeiro, o que é suficiente para os intervalos de entrada fornecidos acima. ( 1e9,4⍴2cria a lista 1e9 2 2 2 2.)

Observe que a fuga para o oeste é feita automaticamente pela conversão de base durante esse processo.

Howard
fonte
Isso é genialidade.
Gareth
7
APLdeveria ser ilegal ...
kiwy
1
@ Kiwy Eu não entendo o seu comentário. Por que o APL deve ser declarado ilegal? Sinta-se à vontade para enviar sua solução de APL também.
Howard
4
@ Kiwy: Isso é mais do que apenas usar APL ... é também uma abordagem muito inteligente da solução, que se encaixa muito bem em um programa APL. É disso que se trata o golfe!
Claudiu
13

GolfScript, 23 22 caracteres

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

Uma abordagem iterativa. A matriz é iterada várias vezes e cada vez que um número de pares é transferido da direita para a esquerda. Experimente o exemplo online .

Breve explicação do 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
fonte
1
+1, isso é mais curto do que qualquer coisa que eu possa encontrar. Agora, se ele só não fosse por isso traquinas "parada na mais ocidental ilha" regra, ~]{2base}2*' '*faria o truque ...
Ilmari Karonen
@IlmariKaronen Escolha o idioma certo (consulte a solução APL ) e a regra traquina fica boa.
Howard
8

GolfScript (25 caracteres)

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

Demonstração online

Solução bastante direta: há uma abordagem mais interessante que define o valor de saída para cada ilha como uma função dos valores de entrada, mas não acho que ele possa ser jogado tão longe quanto realmente seguindo o algoritmo de redistribuição descrito na pergunta.

Peter Taylor
fonte
7

Javascript / ES6 (69)

Jogando com operadores bit a bit:

  • x&=1 mantém o bit mais baixo (1 se ímpar, 0 se for par)
  • x>>1 é a divisão por 2 para números inteiros
f=a=>{a=a.split(' ');for(i=5;--i;a[i]&=1)a[i-1]-=-(a[i]>>1);return a}

Versão sem ES6:

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

Exemplos:
f("3 8 6 0 2")retorna [8, 1, 0, 1, 0]
f("0 997 998 999 1000")retornos[935, 0, 1, 1, 0]

Michael M.
fonte
1
Veja os comentários de Rusher sobre uma das respostas do Python; a entrada deve ser uma sequência seguindo o formato fornecido no exemplo, não uma lista.
Aleksi Torhamo 10/03/2014
@AleksiTorhamo está certo. Permitir uma lista separada por vírgula colocaria seu código em uma vantagem distinta sobre aqueles que seguiram o formato fornecido no exemplo. No futuro, tentarei esclarecer que o formato fornecido no exemplo é o formato. Me desculpe por isso.
Rainbolt
OK, editado. A saída deve ser unida também ou o formato da matriz está ok?
22416 Michael
Eu vim com mais ou menos o mesmo: f=a=>{a=a.split(' ');for(x=5;--x;a[x]&=1)a[x-1]-=-a[x]/2|0;return a}68 caracteres.
MT0 10/03/14
6

Python - 96 caracteres

Golfe pela primeira vez! 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))
Rainbolt
fonte
1
Você pode obtê-lo para baixo para 100 se você compactar o tempo até uma linha usando ponto e vírgula em vez de novas linhas e recuo, e remover o espaço logo após a impressão :)
Aleksi Torhamo
@AleksiTorhamo Thanks. Aprendi também que a divisão inteira em qualquer versão do Python eu usei requer apenas uma única barra, então eu bati-o abaixo de 100.
Rainbolt
1
Ah verdade! Também acabei de perceber que você também pode omitir o ' 'da divisão, reduzindo-o para 96 ​​e superando as outras soluções python2.
Aleksi Torhamo 10/03/2014
5

J (26 caracteres)

Aqui está minha solução em 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

Essa solução geral deve funcionar com qualquer número de ilhas.

Thomas Baruchel
fonte
5

Rubi, 97 90 74 72

Versão online

Golpeou um pouco mais, não invertendo mais a 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
fonte
Você não deve reverter a corda antes de dividir, mas depois. Caso contrário, sua solução poderá gerar resultados incorretos para números de vários dígitos na entrada.
Howard
Eu até considerei as duas "possibilidades" - apesar de não estar ciente dos números com mais de um dígito ...: D Obrigado!
David Herrmann
4

C - 121 caracteres

A entrada é retirada do 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
fonte
É codificado para apenas 5 ilhas?
Geobits 12/03
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
fonte
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 pessoas iniciando em qualquer ilha são equivalentes a X * 2 pessoas iniciando uma ilha à direita. Esse código converte todos na configuração inicial para o equivalente em ilhéus da extrema direita e usa a representação binária do resultado para determinar quantas pessoas acabam em cada ilha.

EDIT: encurtou o código inicializando bpara 1 em vez de 0, permitindo o uso em binvez de uma sequência de formato.

user2357112 suporta Monica
fonte
Usar a representação binária é ingenius! O Lettercount.com deu a você um valor de 85. Você supercontou ou o lettercount é uma ferramenta ruim para usar?
Rainbolt 11/03/14
@Rusher: Minha ferramenta estava usando terminações de linha CRLF. Contando com finais de linha Unix, é 85. #
user2357112 suporta Monica
3

Python (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))

Percorremos a lista de trás para frente e movemos as populações de acordo com a especificação, e depois imprimimos a lista. Aqui está um teste rápido:

>>> 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
fonte
Falhava quando fornecida com a entrada que segue o formato fornecido no exemplo.
Rainbolt
@Rusher Atualizei a resposta para trabalhar com o formato exato usado na pergunta.
arshajii
Outros podem estar em desvantagem se exceções especiais forem permitidas para codificadores Python. Desculpe e obrigado por atualizar sua resposta. Tentarei ser mais claro no futuro que a entrada de exemplo é o formato necessário.
Rainbolt
2

Mathematica 105

Isso deve funcionar com qualquer número de ilhas.

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]]

Exemplos

5 ilhas

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

{8, 1, 0, 1, 0}


25 ilhas

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
fonte
Minha solução produz 270, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0para seus longos dados de teste. Acho que confirmei que estou correto.
OldCurmudgeon
Estranho, dada a forma como funciona. Amanhã vou dar uma olhada no caso.
DavidC
2

Java - 647 533, mas esperando alguns pontos de brownie para o 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;}}

O formulário não compactado:

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);
}

Com uma assistência 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();
  }

}

Um pouco preocupado com o teste 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

gera

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
fonte
2

Java - 196 195

Eu disse a mim mesma que não iria publicá-lo se não pudesse obtê-lo abaixo de 200 ... Sinceramente, acho que não consigo me livrar de mais nada, é muito fino 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]+" "));}}

Quebras de linha:

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]+" "));
    }
}

Saída de entrada de amostra:

$ 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
fonte
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);
    }
}

Saída de amostra:

$ 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
fonte
0

Emacs Lisp 144 chars

Não é pequeno, mas 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
fonte
Você pode adicionar um cabeçalho como #Java - 123 caracteres
Rainbolt 12/14
0

awk - 44 caracteres

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

Java - 116 caracteres

Por exemplo int[] i = {2, 33, 16, 5};(eu acho que aqueles que não são adicionados à contagem, já que cada número pode variar) produziria23 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
fonte
4
Você pode fornecer um compilador que executará esse código? Além disso, o formato e as possíveis fontes para a entrada foram fornecidos na pergunta. Moldar a entrada para uma matriz Java oferece uma vantagem injusta sobre outras.
Rainbolt