Плаваюча Орда


28

Вступ

Дощ нарешті вщух. Більшість людства потонула через помилку в коді @ user12345 . Те, що вижили, розкидані по всьому світовому архіпелагу. Радіозв'язок покращився, і людство готове процвітати ще раз. Без жодної причини, пірати-зомбі зібралися біля головного меридіана і прокотилися на захід. Орда всіх пожирає.

Проблема

Наш сценарій кінця дня може бути описаний 5 цілими числами на одній лінії, що представляють собою набір співпрацюючих острівних громад. Вони впорядковані із заходу (найбільше ліве ціле число) на схід (крайнє право число).

Починаючи з найбільшого сходу острова, острівці втечують парами на наступний найближчий острів. Цікаво, що для кожної пари, яка вирушає, лише одна з них коли-небудь переживає подорож. Острівчани подорожують лише парами. Непарне населення обирає єдиного жителя, щоб залишитися позаду та надавати останні оновлення радіо про витівки орди піратів зомбі. Населення відмовляються подорожувати, поки всі острови на схід від них не закінчать свої міграції або не загинуть. Коли населення досягає остаточного, найбільш західного острова, подорож припиняється.

Керівнику операцій наприкінці світу потрібна програма, яка може вивести кінцевий підрахунок населення кожного села.

Приклад введення

3 8 6 0 2

Приклад Вихід

8 1 0 1 0

Припущення

  • Введення може бути надано через stdin, зчитується з довільно названого файлу або приймається як аргумент
  • Для кожного острова 0 <= населення <= 1024
  • Населення ніколи не пропускають острів

Найкоротша відповідь виграє!


Коли ви говорите аргумент, ви маєте на увазі як аргумент функції або як аргумент командного рядка для програми?
Алексі Торхамо

@AleksiTorhamo аргумент командного рядка, тому він не зараховуватиметься до вашої загальної суми.
Rainbolt

29
Мені подобається ця історія, що охоплює багато запитань про кінець дня.
mikhailcazi

re: "населення ніколи не пропускає острів" - ваш приклад показує, що населення переміщається на кілька островів поспіль. Чи є інше значення, якого я пропускаю?
Аллен Гулд

1
@AllenGould Населення дійсно переміщувалося по декількох островах, але жодного разу їх не пропустило. Якби на крайньому правому острові було 32 людини, вони загинули б, як 16, 8, 4, і нарешті 2 дісталися б до крайнього лівого острова.
Rainbolt

Відповіді:


26

APL, 16 символів

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

Вхід подається як рядок до цього блоку:

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

або на один знак менше, якщо введення подано як аргумент до цього блоку:

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

Він заснований на ідеї Ілмарі Каронен у цьому коментарі .

  • 2⊥⍵ робить перетворення бази 2 на вході.
  • (1e9,4⍴2)⊤таким чином перетворює це число назад в базу 2 (для чотирьох останніх цифр) і базу 1e9 для першої, що достатньо для введених вище діапазонів. ( 1e9,4⍴2будує список 1e9 2 2 2 2.)

Зауважте, що біг на захід здійснюється автоматично шляхом базового перетворення під час цього процесу.


Це геній.
Гарет

7
APLповинні бути незаконними ...
Kiwy

1
@Kiwy Я не розумію твій коментар. Чому APL слід визнати незаконним? Не соромтеся також надіслати своє рішення APL.
Говард

4
@Kiwy: Це більше, ніж просто використання APL ... це також дуже розумний підхід до рішення, який, як буває, дуже акуратно вписується в програму APL. Це те, про що йдеться у гольф!
Клавдіу

13

GolfScript, 23 22 символи

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

Ітеративний підхід. Масив повторюється кілька разів, і кожен раз, коли кількість пар передається справа наліво. Спробуйте приклад в Інтернеті .

Коротке пояснення коду:

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

1
+1, це коротше, ніж усе, що я міг знайти. Тепер, якби не тільки це ~]{2base}2*' '*
примхливе

@IlmariKaronen Виберіть потрібну мову (див. Рішення APL ) і прискіпливе правило стає нормальним.
Говард

8

GolfScript (25 символів)

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

Демонстрація в Інтернеті

Досить просте рішення: є більш цікавий підхід, який визначає вихідне значення для кожного острова як функцію від вхідних значень, але я не думаю, що це може бути майже так далеко, як насправді за алгоритмом перерозподілу, описаним у питанні.


7

Javascript / ES6 (69)

Гра з розрядними операторами:

  • x&=1 зберігає найнижчий біт (1, якщо непарне, 0, якщо парне)
  • x>>1 це ділення на 2 для цілих чисел
f=a=>{a=a.split(' ');for(i=5;--i;a[i]&=1)a[i-1]-=-(a[i]>>1);return a}

Версія без ES6:

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

Приклади:
f("3 8 6 0 2")повертає [8, 1, 0, 1, 0]
f("0 997 998 999 1000")прибутки[935, 0, 1, 1, 0]


1
Дивіться коментарі Рушера до однієї з відповідей Python; вхід повинен бути рядок, що слідує за форматом, наведеним у прикладі, а не списком.
Алексі Торхамо

@AleksiTorhamo має рацію. Дозволення списку, розділеного комами, надасть вашому коду перевагу перед тими, хто дотримувався формату, наведеного в прикладі. Надалі я постараюся бути зрозумілішим, що формат, наданий у прикладі, - це формат. Вибач за це.
Rainbolt

Добре, відредаговано. Чи слід також приєднати висновок чи нормальний формат масиву?
Майкл М.

Я придумав більш-менш те саме: f=a=>{a=a.split(' ');for(x=5;--x;a[x]&=1)a[x-1]-=-a[x]/2|0;return a}це 68 символів.
MT0

6

Пітон - 96 символів

Перший раз гольф! Введення від 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))

1
Ви можете зменшити його до 100, якщо стиснути час до одного рядка, використовуючи крапки з комою замість нових рядків і відступів, а пробіл видаліть безпосередньо після друку :)
Aleksi Torhamo

@AleksiTorhamo Дякую Я також дізнався, що для цілого поділу в будь-якій версії Python, яку я використовував, потрібна лише одна коса риса, тому я збив її нижче 100.
Rainbolt

1
Ах, правда! Я також щойно зрозумів, що ви можете також опустити цей ' 'розділ, знизивши його до 96 і побивши інші рішення python2.
Алексі Торхамо

5

J (26 символів)

Ось моє рішення в 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

Це загальне рішення має працювати з будь-якою кількістю островів.


5

Рубі, 97 90 74 72

Інтернет-версія

Гольфував це трохи далі, більше не повертаючи масив ...

f=->i{i=i.split.map(&:to_i);(1..4).each{|n|i[-n-1]+=i[-n]/2;i[-n]%=2};i}

Ви не повинні перевертати рядок перед розділенням, а після. Інакше ваше рішення може дати неправильні результати для багатоцифрових чисел на вводі.
Говард

Я навіть розглядав обидві "можливості" - хоч і не знаю числа з більш ніж однією цифрою ...: D Дякую!
Девід Геррман

4

C - 121 символ

Введення взято з 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;}

Це жорстке кодування лише для 5 островів?
Геобіц

4

Python2 - 98 символів

Введення від 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 символів

Введення від stdin.

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

4

Python 2, 85 80 байт

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

X людей, що починаються на будь-якому острові, еквівалентні X * 2 людям, що починають один острів праворуч. Цей код перетворює всіх у стартовій конфігурації у їх еквівалент у крайніх правих островах, а потім використовує двійкове представлення результату, щоб визначити, скільки людей потрапляє на кожен острів.

EDIT: Скоротіть код, ініціалізувавшись bна 1 замість 0, дозволяючи використовувати binзамість рядка формату.


Використання двійкового представлення - це геніальність! Lettercount.com дав вам 85. Ви переплачували чи це поганий інструмент?
Rainbolt

@Rusher: Мій інструмент використовував закінчення рядків CRLF.
Підрахувавши

3

Пітон (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))

Ми прокручуємо список зі спини вперед і переміщуємо групи відповідно до специфікації, після чого роздруковуємо список. Ось швидкий тест:

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

Збито, якщо він надається вводом, який відповідає формату, наведеному в прикладі.
Rainbolt

@Rusher Я оновив відповідь, щоб працювати з точним форматом, який використовується у питанні.
Аршаджій

Інші можуть опинитися в невигідному становищі, якщо для кодерів Python допускаються спеціальні винятки. Вибачте і дякую за оновлення вашої відповіді. Я спробую в майбутньому зрозуміти, що приклад прикладу - це необхідний формат.
Rainbolt

2

Математика 105

Це повинно працювати з будь-якою кількістю островів.

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

Приклади

5 островів

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

{8, 1, 0, 1, 0}


25 островів

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


Моє рішення створює 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

Дивно, враховуючи, як це працює. Я завтра погляну на справу.
DavidC

2

Java - 647 533, але сподіваюся на деякі точки брауні для потоків Java 8.

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

Нестиснута форма:

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

За сприяння:

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

}

Трохи стурбований тестом @ 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

породжує

270, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0

2

Ява - 196, 195

Я сказав собі, що не буду публікувати його, якщо не зможу отримати його під 200 ... Я, чесно кажучи, не думаю, що я можу позбутися нічого іншого, для 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]+" "));}}

Розриви рядків:

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

Зразок вхідного виходу:

$ 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

2

Java - 179 символів

Стислий:

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

Звичайний:

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

Вибірка зразка:

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

$ java F 7 6 5 4 3
11 1 1 1 1

0

Emacs Lisp 144 символів

Не крихітний, але це працює

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

Ви можете додати заголовок на зразок #Java - 123 Персонажі
Rainbolt


-2

Java - 116 символів

Наприклад int[] i = {2, 33, 16, 5};(я думаю, що вони не додають до підрахунку, оскільки кожне число може змінюватися) виводиться23 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] + " ");
}

4
Чи можете ви надати компілятор, який виконуватиме цей код? Також у питанні було вказано формат та можливі джерела введення. Формування вводу в масив Java дає несправедливу перевагу перед іншими.
Rainbolt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.