Плавающая Орда

28

Введение

Дождь наконец утих. Большая часть человечества утонула из-за ошибки в коде @ user12345 . Оставшиеся в живых разбросаны по всему миру архипелага. Радиосвязь налажена, и человечество готово процветать еще раз. Без всякой причины пираты-зомби собрались у Первого меридиана и несутся на запад. Орда пожирает все.

проблема

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

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

Управляющему операциями в конце света нужна программа, которая может выводить итоговые данные о численности населения каждой деревни.

Пример ввода

3 8 6 0 2

Пример вывода

8 1 0 1 0

Предположения

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

Кратчайший ответ выигрывает!

Rainbolt
источник
Когда вы произносите аргумент, вы имеете в виду аргумент функции или аргумент командной строки программы?
Алекси Торхамо
@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
@ Киви, я не понимаю твой комментарий. Почему 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 символов

Первый раз в гольф! Ввод от стандартного ввода.

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
источник
1
Вы можете уменьшить его до 100, если вы сократите время до одной строки, используя точки с запятой вместо новых строк и отступов, и удалите пробел сразу после печати :)
Алекси Торхамо,
@ 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 символов

Ввод взят из стандартного ввода.

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
источник
Это жестко запрограммировано только для 5 островов?
Geobits
4

Python2 - 98 символов

Ввод от стандартного ввода.

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 символов

Ввод от стандартного ввода.

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 человекам, начинающим один остров справа. Этот код преобразует всех в начальной конфигурации в их эквивалент у крайне правых островитян, а затем использует двоичное представление результата, чтобы определить, сколько людей окажется на каждом острове.

РЕДАКТИРОВАТЬ: Сократить код, инициализируя b1 вместо 0, что позволяет использовать binвместо строки формата.

user2357112 поддерживает Monica
источник
Использование бинарного представления - это гениальность! Lettercount.com дал вам 85. Вы пересчитали или Lettercount плохой инструмент для использования?
Rainbolt
@Rusher: Мой инструмент использовал концы строк CRLF. Считая это с окончаниями строки Unix, это 85.
user2357112 поддерживает Monica
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
arshajii
источник
Сбой при вводе в соответствии с форматом, приведенным в примере.
Rainbolt
@Rusher Я обновил ответ, чтобы работать с точным форматом, используемым в вопросе.
Аршаджи
Другие могут оказаться в невыгодном положении, если для кодировщиков Python разрешены специальные исключения. Извините, и спасибо за обновление вашего ответа. В будущем я постараюсь прояснить, что пример ввода - это требуемый формат.
Rainbolt
2

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

DavidC
источник
Мое решение производит 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

Джава - 647 533, но надеемся на несколько очков брауни для 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;}}

Несжатая форма:

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
OldCurmudgeon
источник
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
Geobits
источник
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
0

awk - 44 персонажа

{for(i=NF;i>1;){n=int($i/2);$i%=2;$--i+=n}}1
laindir
источник
-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 дает вам несправедливое преимущество перед другими.
Рейнболт