Gerombolan Mengambang

28

pengantar

Hujan akhirnya reda. Sebagian besar manusia tenggelam karena bug dalam kode @ user12345 . Korban tersebar di seluruh kepulauan di seluruh dunia. Komunikasi radio meningkat, dan umat manusia siap untuk berkembang sekali lagi. Tanpa alasan apa pun, bajak laut zombie telah berkumpul di Meridian Perdana, dan menyapu ke arah barat. Gerombolan itu melahap semua.

Masalah

Skenario kiamat kami dapat dijelaskan oleh 5 bilangan bulat pada satu garis yang mewakili sekumpulan komunitas pulau yang bekerja sama. Mereka dipesan dari barat (integer paling kiri) ke timur (integer paling kanan).

Dimulai dengan pulau paling jauh ke timur, penduduk pulau berpasangan dengan pulau terdekat berikutnya. Anehnya, untuk setiap pasangan yang memulai, hanya satu dari mereka yang pernah selamat dari perjalanan. Penduduk pulau hanya bepergian berpasangan. Populasi ganjil memilih satu-satunya penghuni untuk tetap tinggal dan memberikan pembaruan radio terbaru tentang kejenakaan gerombolan bajak laut zombie. Populasi menolak untuk melakukan perjalanan sampai semua pulau di sebelah timur mereka menyelesaikan migrasi mereka atau mati. Ketika populasi mencapai pulau terakhir, paling barat, perjalanan berhenti.

Manajer operasi di ujung dunia membutuhkan program yang dapat menampilkan jumlah populasi akhir dari setiap desa.

Contoh Input

3 8 6 0 2

Contoh Output

8 1 0 1 0

Asumsi

  • Masukan dapat diberikan melalui stdin, membaca dari file yang dinamai secara sewenang-wenang, atau diterima sebagai argumen
  • Untuk setiap pulau, 0 <= populasi <= 1024
  • Populasi tidak pernah melewati satu pulau

Jawaban terpendek menang!

Rainbolt
sumber
Ketika Anda mengatakan argumen, apakah maksud Anda sebagai argumen untuk suatu fungsi atau sebagai argumen baris perintah ke program?
Aleksi Torhamo
@AleksiTorhamo Command-line arg, jadi tidak akan dihitung terhadap total Anda.
Rainbolt
29
Saya suka cerita kiamat yang mencakup banyak pertanyaan ini.
mikhailcazi
re: "populasi tidak pernah melewati satu pulau" - contoh Anda menunjukkan populasi memindahkan banyak pulau secara berurutan. Apakah ada arti lain yang saya lewatkan?
Allen Gould
1
@ AllenGould Populasi memang bergerak melintasi beberapa pulau, tetapi mereka tidak pernah melewatkan satu pun. Jika ada 32 orang di pulau paling kanan, mereka akan mati seperti 16, 8, 4, dan akhirnya 2 akan mencapai pulau paling kiri.
Rainbolt

Jawaban:

26

APL, 16 karakter

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

Input diberikan sebagai string ke blok ini:

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

atau satu karakter lebih sedikit jika input diberikan sebagai argumen untuk blok ini:

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

Hal ini didasarkan pada gagasan Ilmari Karonen dalam komentar ini .

  • 2⊥⍵ melakukan konversi basis 2 dari input.
  • (1e9,4⍴2)⊤dengan demikian mengkonversi angka ini kembali ke basis 2 (untuk empat digit terakhir) dan basis 1e9 untuk yang pertama, yang cukup untuk rentang input yang diberikan di atas. ( 1e9,4⍴2membuat daftar 1e9 2 2 2 2.)

Perhatikan bahwa barat yang melarikan diri dilakukan secara otomatis oleh konversi basis selama proses ini.

Howard
sumber
Ini jenius.
Gareth
7
APLharus ilegal ...
Kiwy
1
@ Kyiwy Saya tidak mengerti komentar Anda. Mengapa APL harus dinyatakan ilegal? Jangan ragu untuk mengirimkan solusi APL Anda juga.
Howard
4
@ Kwiwy: Ini lebih dari sekedar menggunakan APL ... ini juga pendekatan yang sangat pintar untuk solusi, yang kebetulan sangat cocok dengan program APL. Inilah yang dimaksud dengan golf!
Claudiu
13

GolfScript, 23 22 karakter

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

Pendekatan berulang. Array diulang beberapa kali dan setiap kali sejumlah pasangan ditransfer dari kanan ke kiri. Coba contoh online .

Penjelasan singkat tentang kode:

~]       # 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
sumber
1
+1, ini lebih pendek dari yang bisa saya temukan Sekarang, jika bukan karena aturan "berhenti di pulau paling barat" yang sial itu, ~]{2base}2*' '*akan melakukan trik ...
Ilmari Karonen
@IlmariKaronen Pilih bahasa yang tepat (lihat solusi APL ) dan aturan sial menjadi baik.
Howard
8

GolfScript (25 karakter)

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

Demo online

Solusi yang sangat mudah: ada pendekatan yang lebih menarik yang mendefinisikan nilai output untuk masing-masing pulau sebagai fungsi dari nilai input, tetapi saya tidak berpikir itu bisa di-golf hampir sejauh mengikuti algoritma redistribusi yang dijelaskan dalam pertanyaan.

Peter Taylor
sumber
7

Javascript / ES6 (69)

Bermain dengan operator bitwise:

  • x&=1 menjaga bit terendah (1 jika ganjil, 0 jika genap)
  • x>>1 adalah pembagian dengan 2 untuk bilangan bulat
f=a=>{a=a.split(' ');for(i=5;--i;a[i]&=1)a[i-1]-=-(a[i]>>1);return a}

Versi tanpa ES6:

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

Contoh:
f("3 8 6 0 2")mengembalikan [8, 1, 0, 1, 0]
f("0 997 998 999 1000")pengembalian[935, 0, 1, 1, 0]

Michael M.
sumber
1
Lihat komentar Rusher pada salah satu jawaban Python; input harus berupa string mengikuti format yang diberikan dalam contoh, bukan daftar.
Aleksi Torhamo
@AleksiTorhamo benar. Mengizinkan daftar yang dipisahkan koma akan menempatkan kode Anda pada keuntungan yang berbeda dibandingkan mereka yang mengikuti format yang disediakan dalam contoh. Di masa depan, saya akan mencoba untuk menjadi lebih jelas bahwa format yang disediakan dalam contoh adalah yang Format. Maaf soal itu.
Rainbolt
OKE, diedit. Haruskah output bergabung juga atau format array tidak apa-apa?
Michael M.
Saya datang dengan kurang lebih sama: f=a=>{a=a.split(' ');for(x=5;--x;a[x]&=1)a[x-1]-=-a[x]/2|0;return a}yaitu 68 karakter.
MT0
6

Python - 96 Karakter

Pertama kali bermain golf! Masukan dari 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
sumber
1
Anda dapat menurunkannya hingga 100 jika Anda mengompres sementara ke satu baris dengan menggunakan titik koma alih-alih baris baru dan lekukan, dan menghapus ruang secara langsung setelah mencetak :)
Aleksi Torhamo
@AleksiTorhamo Terima kasih. Saya juga belajar bahwa pembagian integer dalam versi Python apa pun yang saya gunakan hanya membutuhkan satu tebasan, jadi saya mengetuknya di bawah 100.
Rainbolt
1
Ah benar! Saya juga baru sadar Anda juga dapat menghilangkan ' 'dari split, membawanya ke 96 dan mengalahkan solusi python2 lainnya.
Aleksi Torhamo
5

J (26 karakter)

Ini solusi saya di 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

Solusi umum ini harus bekerja dengan sejumlah pulau.

Thomas Baruchel
sumber
5

Rubi, 97 90 74 72

Versi online

Golf sedikit lebih jauh, tidak membalikkan array lagi ...

f=->i{i=i.split.map(&:to_i);(1..4).each{|n|i[-n-1]+=i[-n]/2;i[-n]%=2};i}
David Herrmann
sumber
Anda tidak boleh membalik string sebelum membelah tetapi setelah. Kalau tidak, solusi Anda dapat menghasilkan hasil yang salah untuk angka multi-digit dalam input.
Howard
Saya bahkan menganggap kedua "kemungkinan" - meskipun tidak mengetahui angka dengan lebih dari satu digit ...: D Terima kasih!
David Herrmann
4

C - 121 karakter

Input diambil dari 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
sumber
Apakah ini hanya kode untuk 5 pulau?
Geobits
4

Python2 - 98 karakter

Masukan dari 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 karakter

Masukan dari 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
sumber
4

Python 2, 85 80 byte

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

X orang yang memulai di pulau mana pun setara dengan X * 2 orang yang memulai satu pulau di sebelah kanan. Kode ini mengonversi setiap orang dalam konfigurasi awal ke yang setara di pulau kanan-jauh, kemudian menggunakan representasi biner dari hasilnya untuk menentukan berapa banyak orang yang berakhir di setiap pulau.

EDIT: Mempersingkat kode dengan menginisialisasi bke 1 bukannya 0, memungkinkan penggunaan binalih-alih string format.

user2357112 mendukung Monica
sumber
Menggunakan representasi biner adalah ingenius! Lettercount.com memberi Anda 85. Apakah Anda menghitung berlebihan, atau apakah lettercount alat yang buruk untuk digunakan?
Rainbolt
@Rusher: Alat saya menggunakan ujung garis CRLF. Menghitungnya dengan ujung garis Unix, itu 85.
user2357112 mendukung 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))

Kami mengulang daftar dari belakang ke depan dan memindahkan populasi di sekitar sesuai dengan spesifikasi, kemudian mencetak daftar. Inilah tes cepat:

>>> 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
sumber
Hancur ketika disediakan dengan input yang mengikuti format yang disediakan dalam contoh.
Rainbolt
@Rusher Saya memperbarui jawaban untuk bekerja dengan format tepat yang digunakan dalam pertanyaan.
arshajii
Orang lain mungkin dirugikan jika pengecualian khusus diizinkan untuk pembuat kode Python. Maaf, dan terima kasih telah memperbarui jawaban Anda. Saya akan mencoba untuk menjadi lebih jelas di masa depan bahwa contoh input adalah format yang diperlukan.
Rainbolt
2

Mathematica 105

Ini harus bekerja dengan sejumlah pulau.

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

Contohnya

5 pulau

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

{8, 1, 0, 1, 0}


25 pulau

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, 1, 0 }

DavidC
sumber
Solusi saya menghasilkan 270, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0data uji panjang Anda. Saya pikir saya sudah mengkonfirmasi bahwa saya benar.
OldCurmudgeon
Aneh, mengingat cara kerjanya. Saya akan melihat besok kasusnya.
DavidC
2

Jawa - 647 533 tetapi berharap untuk beberapa poin brownies untuk Java 8 Streaming.

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

Bentuk terkompresi:

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

Dengan bantuan:

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

}

Sedikit khawatir bahwa uji @ 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

menghasilkan

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

Jawa - 196 195

Saya berkata pada diri sendiri bahwa saya tidak akan mempostingnya jika saya tidak bisa mendapatkannya di bawah 200 ... Jujur saya tidak berpikir saya bisa menyingkirkan hal lain, itu cukup tipis untuk Jawa.

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

Jeda baris:

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

Output input sampel:

$ 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
Geobit
sumber
2

Java - 179 karakter

Terkompresi:

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

Output sampel:

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

Emacs Lisp 144 karakter

Tidak mungil, tetapi berhasil

(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
sumber
Anda dapat menambahkan tajuk seperti #Java - 123 Karakter
Rainbolt
0

awk - 44 Karakter

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

Java - 116 Karakter

Sebagai contoh int[] i = {2, 33, 16, 5};(saya kira itu tidak menambah hitungan, karena setiap angka dapat bervariasi) akan menghasilkan23 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
sumber
4
Bisakah Anda memberikan kompiler yang akan menjalankan kode ini? Juga, format dan sumber-sumber yang mungkin untuk input disediakan dalam pertanyaan. Molding input ke array Java memberi Anda keuntungan yang tidak adil atas yang lain.
Rainbolt