Порахуйте сліди правди


59

Натхненний моїм дорогим другом і колегою і на згадку про нього,

Ден Баронет

Ден Баронет , 1956 - 2016. RIP

Він знайшов найкоротше можливе рішення APL для цього завдання:

Завдання

Враховуючи булевий список, підрахуйте кількість значень правди, що відривається.

Приклади випадків

{}0

{0}0

{1}1

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

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

{1, 1, 0, 1, 1}2

{0, 0, 1, 1, 1}3

{1, 1, 1, 1, 1, 1}6


Чи можемо ми прийняти список як рядок нулів та одиниць? наприклад 01100?
Аднан

@Adnan, тільки якщо це найбільш нормальний спосіб представлення булевих списків.
Адам

71
Співчуваю вашій втраті.
Мартін Ендер

6
@MartinEnder Дякую Буде важко йти вперед. Ден навчив мене всього, що мені потрібно було знати, щоб працювати для Діялога.
Адам

5
Прощання з Даном. RIP ...
Ерік Атголфер

Відповіді:


36

Діалог APL, 6 2 байти

⊥⍨

Перевірте його на TryAPL .

Як це працює

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

Для базового вектора b = b n , ⋯, b 0 і цифрового вектора a = a n , ⋯, a 0 , b ⊥ a перетворюється a в змішану основу b , тобто обчислює b 0 ⋯ b n-1 a n + ⋯ + b 0 b 1 a 2 + b 0 a 1 + a 0 .

Тепер (tilde dieresis, comute) модифікує оператор ліворуч наступним чином. У монадійному контексті він викликає оператора з рівними аргументами зліва і справа.

Наприклад, ⊥⍨ визначається як , який обчислює 0п + ⋯ + а 0 1 2 + а 0 1 + а 0 , то сума всіх кумулятивних продуктів від справа наліво .

Для K завершальних одиниць, то K правих продукти 1 , а всі інші є 0 , тому їх сума дорівнює K .


14
Підказка: Ден зробив це лише у двох байтах.
Adám

3
Змішане базове перетворення! Це розумно.
Денніс

1
Ой. Змішане базове перетворення, як воно вражає знову.
Conor O'Brien

Браво! Насправді, через Ден, ми спеціально розглядали b⊥bі ⊥⍨bвідмовлялися від нескінченної швидкості.
Adám

19

JavaScript (ES6), 21 байт

f=l=>l.pop()?f(l)+1:0

Тестові кейси


Як це працює? Як f(l)+1повертає значення > 2?
Олівер

@Oliver Це рекурсивний процес, який оцінюється як l.pop()?(l.pop()?(l.pop()?(...etc...)+1:0)+1:0)+1:0.
Арнольд

Я бачу. Дякую за пояснення.
Олівер

11

Желе , 4 байти

ŒrṪP

Спробуйте в Інтернеті! або Перевірте всі тестові випадки.

У випадку, коли список порожній, є кілька цікавих спостережень. По-перше, кодування довжиною запуску []повертає ще один порожній список []. Потім відновлення останнього елемента з цього, використовуючи хвостові повернення 0замість пари, [value, count]які є регулярними елементами кодованого масиву довжиною прогону. Потім продукт Pповертається, 0коли викликається, на 0якому очікуваний результат.

Пояснення

ŒrṪP  Main link. Input: list M
Œr    Run-length encode
  Ṫ   Tail, get the last value
   P  Product, multiply the values together

Як варіант ŒgṪS, теж працює!
Лінн

Це дає правильний вихід для порожнього списку як вхідний, але я здивований, отриманий розріз. Ви б не хотіли пройти через цей особливий випадок?
Пітер Тейлор

@PeterTaylor Я теж дивуюсь, що це спрацювало. Також я щойно помітив, що перше посилання має неправильний код.
милі

@PeterTaylor в желе реалізований в вигляді: lambda z: iterable(z).pop() if iterable(z) else 0. iterableколи викликається у списку, просто повертає список, а порожній список, звичайно, хибний.
FryAmTheEggman



10

Haskell, 26 25 байт

a%b|b=1+a|0<3=0
foldl(%)0

Використання:

Prelude> foldl(%)0 [True,False,True,True]
2

Версія Pointfree (26 байт):

length.fst.span id.reverse

Використання цілого списку замість списку bool (21 байт, завдяки Крістіану Сіверсу):

a%b=b*(a+1)
foldl(%)0

Використання:

Prelude> foldl(%)0 [1,0,1,1]
2

Версія Pointfree (25 байт)

sum.fst.span(==1).reverse

Для цілих списків foldlідея працює зa%b=b*(a+1)
Christian Sievers

9

Сітківка , 7 5 байт

r`1\G

Спробуйте в Інтернеті! (Перший рядок включає тестовий набір, відокремлений виведенням ліній.)

Визначення формату введення для Retina не зовсім однозначне. Оскільки у Retina немає поняття будь-якого типу, крім рядків (а також не має значення, яке можна використати для нашого звичайного визначення truthy та falesy), я зазвичай використовую 0та 1(або щось позитивне взагалі), щоб відповідати truthy та falesy, як вони представляють нуль або деякі відповідники відповідно.

З односимвольними поданнями нам також не потрібен роздільник для списку (який певним чином є більш природним поданням списку для мови, що має лише рядки). Adám підтвердив, що це прийнятний формат введення.

Що стосується самого регулярного виразів, то він збігається від rправого наліво і \Gприв'язує кожну відповідність до попередньої. Отже, це підраховує, скільки 1с ми можемо відповідати в кінці рядка.


"Так, для Retina, оскільки він обробляє лише рядки, я думаю, що рядок" 01 "або" FT "є в порядку.
Adám

9

05AB1E , 12 10 6 5 байт

Збережено 1 байт завдяки carusocomputing .

Î0¡¤g

Спробуйте в Інтернеті!

Пояснення

Î      # push 0 and input
 0¡    # split on 0
   ¤   # take last item in list
    g  # get length

0¡¤g- чотири байти.
Чарівний восьминіг Урна

@carusocomputing: Приємно! Ще не було уточнено, чи було введення рядків добре, коли я це писав, але зараз я бачу, що це :)
Emigna

J0¡¤gще коротше;).
Чарівний восьминіг Урна

@carusocomputing: На жаль, нам потрібно Îобробити порожній вхід, але все-таки байт збережено дякую :)
Emigna




7

Математика, 25 24 байти

Fold[If[#2,#+1,0]&,0,#]&

3
Тільки записуємо порт класного змішаного базового рішення Дена: FromDigits[b=Boole@#,MixedRadix@b]&(35 байт).
Грег Мартін


5

C90 (gcc), 46 байт

r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}

Введення здійснюється через аргументи командного рядка (одне ціле число на аргумент), вихід - через вихідний код .

Спробуйте в Інтернеті!

Як це працює

r - глобальна змінна. Його тип за замовчуванням до int і, будучи глобальним, він значення за замовчуванням до 0 .

Аргумент функції c за замовчуванням також для int . Він буде містити ціле число n + 1 для масивів n булевих; перший аргумент main - це завжди шлях до виконуваного файлу.

Аргумент функції v оголошується як int**. Фактичний тип v буде char**, але оскільки ми розглянемо лише найменш значущий біт кожного аргументу, щоб повідомити символи 0 (кодова точка 48 ) та 1 (кодова точка 49 ), це не має значення для маленького ендіана машини.

Зменшення циклу while c і порівнює його з 0 . Як тільки c досягне 0 , ми вирвемося з циклу. Це потрібно, лише якщо масив не містить 0 's.

Поки 0<--cповертається 1 , ми беремо c- й аргумент командного рядка ( v[c]) і витягуємо його перший символ за допомогою перенаправлення покажчика ( *). Візьмемо побітові AND булевого 0<--cта кодового пункту символу (і три байти сміття, що слідують за ним), тому умова повернеться 0, коли зустрінеться 0 , вириваючись із циклу.

У останньому випадку, хоча аргументи командного рядка дорівнюють 1 , з r++кроком r на 1 , таким чином підраховуючи кількість кінцевих 1 -х.

Нарешті, c=rзберігає обчислене значення r у c . За допомогою налаштувань за замовчуванням компілятор оптимізує та видаляє призначення; він фактично генерує movl %eax, -4(%rbp)інструкцію. Оскільки retповертає значення регістру EAX, це генерує бажаний вихід.

Зауважте, що цей код не працює з C99, який повертає 0 з основного, якщо досягнуто кінця основного .


Чи argcне принаймні 1(із argv[0]вмістом файлу)? Ви можете зберегти один байт, --c&&а не 0<--c&. код виходу gcc береться argc? Акуратний.
Тит

@Titus Це не спрацює. *v[c]є кодовою точкою 1 або 0 , тож це або 49, або 48 і, таким чином, завжди є правдою.
Денніс

З C89 та C90 gcc повертає все, що є в RAX на той момент. C99 завжди повертає 0 від основного, якщо досягнуто кінця.
Денніс

4

k, 6 байт

+/&\|:

Ця функція композиція перекладається sum mins reverseв qбільш читається родинних засобах мови, де хв є мінімальною прокаткою.


Можна: кинути?
Стрітер

4

J, 9 3 байти

#.~

Це рефлексивне змішане базове перетворення. Тому що це те саме, що змішане базове перетворення. Знову.

Тестові кейси

   v =: #.~
   ]t =: '';0;1;0 1 1 0 0;1 1 1 0 1;1 1 0 1 1;0 0 1 1 1;1 1 1 1 1 1
++-+-+---------+---------+---------+---------+-----------+
||0|1|0 1 1 0 0|1 1 1 0 1|1 1 0 1 1|0 0 1 1 1|1 1 1 1 1 1|
++-+-+---------+---------+---------+---------+-----------+
   v&.> t
+-+-+-+-+-+-+-+-+
|0|0|1|0|1|2|3|6|
+-+-+-+-+-+-+-+-+
   (,. v&.>) t
+-----------+-+
|           |0|
+-----------+-+
|0          |0|
+-----------+-+
|1          |1|
+-----------+-+
|0 1 1 0 0  |0|
+-----------+-+
|1 1 1 0 1  |1|
+-----------+-+
|1 1 0 1 1  |2|
+-----------+-+
|0 0 1 1 1  |3|
+-----------+-+
|1 1 1 1 1 1|6|
+-----------+-+

2
Підказка: це можна зробити лише в 3 байтах, використовуючи J-переклад рішення Дана.
Адам

1
@ Adám Я намагався шукати рішення. Не думав про перетворення бази. Це справді досить розумно від нього!
Conor O'Brien

1
Так. Це був Дан. :-(
Adám

4

R, 40 39 25 байт

Повністю перероблене рішення завдяки @Dason

sum(cumprod(rev(scan())))

Прочитайте вхід з stdin, поверніть вектор і, якщо перший елемент, !=0то виведіть першу довжину кодування довжини пробігу ( rle), інакше 0.


1
Ви можете зберегти байт, змінивши другий рядок на ifelse(r$v,r$l,0)[1]. (Векторизовано, якщо, а потім візьміть перший елемент.)
rturnbull

1
немає потреби в iflelse - просто помножте r $ v і r $ l.
Дейсон

Але маршрут (cumprod (rev (.))) Все одно повинен економити багато байт
Dason

3

Haskell, 24 байти

foldl(\a b->sum[a+1|b])0

Ітерація над списком, додавання по одному для кожного елемента, обнулення 0після введення а False.

16 байт з входом 0/1:

foldl((*).(+1))0

Якщо список гарантується не порожнім, ми можемо отримати 14 байт:

sum.scanr1(*)1

Це обчислює сукупний продукт із зворотного боку, а потім підсумовує їх. Сукупний добуток залишається 1, доки не буде досягнуто 0, а потім стане 0. Отже, 1 відповідає рівним знакам 1.



3

C # 6, 103 72 байти

using System.Linq;
int a(bool[] l)=>l.Reverse().TakeWhile(x=>x).Count();

Використання негенеричного списку побиває загальний список на 1 байт лол

-31 байт завдяки Скотту


Якщо ви використовуєте масив ints, ви можете пітиint a(int[] l)=>l.Reverse().TakeWhile(i=>i>0).Sum();
Скотт

@Scott Звичайно, що я думав ... я буду дотримуватися bool, хоча. Питання вказує логічний список, і це не C.
Посилання Ng

Компілюйте до Func<bool[], int>57 байт, тобтоusing System.Linq;l=>l.Reverse().TakeWhile(x=>x).Count();
TheLethalCoder


2

DASH , 16 байт

@len mstr"1+$"#0

Це не найкоротший з можливих рішень DASH, але найкоротший з можливих рішень DASH переймається на мене. Я розміщую цей романний підхід на своєму місці.

Використання:

(@len mstr"1+$"#0)"100111"

Пояснення

@(                 #. Lambda
  len (            #. Get the length of the array after...
    mstr "1+$" #0  #. ... matching the argument with regex /1+$/
  )                #. * mstr returns an empty array for no matches
)

2

Скала, 25 байт

l=>l.reverse:+0 indexOf 0

Безголівки:

l=>(l.reverse :+ 0).indexOf(0)

Перевертає список, додає 0 і знайде перший індекс 0, який є кількістю елементів перед першим 0


2

Пакет, 57 байт

@set n=0
@for %%n in (%*)do @set/an=n*%%n+%%n
@echo %n%

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



2

Java 7, 62 байти

int c(boolean[]a){int r=0;for(boolean b:a)r=b?r+1:0;return r;}

Невикористаний і тестовий код:

Спробуйте тут.

class M{
  static int c(boolean[] a){
    int r = 0;
    for (boolean b : a){
      r = b ? r+1 : 0;
    }
    return r;
  }

  public static void main(String[] a){
    System.out.print(c(new boolean[]{}) + ", ");
    System.out.print(c(new boolean[]{ false }) + ", ");
    System.out.print(c(new boolean[]{ true }) + ", ");
    System.out.print(c(new boolean[]{ false, true, true, false, false }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, false, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, false, true, true }) + ", ");
    System.out.print(c(new boolean[]{ false, false, true, true, true }) + ", ");
    System.out.print(c(new boolean[]{ true, true, true, true, true, true }));
  }
}

Вихід:

0, 0, 1, 0, 1, 2, 3, 6

2

Perl 5,10, 22 байти

21 байт + 1 байт для -aпрапора. Оскільки вираз на основі регулярних виразів був виконаний ...: с

Вхідні значення масиву повинні бути розділені пробілом.

$n++while pop@F;say$n

Спробуйте в Інтернеті!


1
Трохи коротше, якщо ви приймете аргументи через командний рядок: perl -E '$_++while pop;say' 0 1 1 0 1 1 1але це нічого не виводить 0(не впевнений, чи це проблема!)
Дом Гастінгс

2

Perl, 22 байти

21 байт коду + 1 байт для -pпрапора.

s/.(?=.*0)//g;$_=y;1;

Щоб запустити його:

perl -pE 's/.(?=.*0)//g;$_=y;1;' <<< "0 1 1 0 1 1 1"

( На насправді, формат вводу не має значення , багато: 0110111, 0 1 1 0 1 1 1, і [0,1,1,0,1,1,1]т.д. б всі роботи)


Версія з 18 байтами від @Dom Hastings, але вона вимагає надати вхід у вигляді рядків 0 і 1, що не дозволено:

perl -pE '/1*$/;$_=length$&' <<< '0110111'

Люблю цю ;хитрість :) Якщо формат - одна суцільна струна: perl -pE '/1*$/;$_=length$&' <<< '0110111'для 18 років, не впевнений, чи це згинає правила чи ні, хоча ...
Дом Гастінгс

@DomHastings так, і я! (Дякую Тон за те, що мені це показали!) Перший та другий коментарі запитання начебто забороняють формат введення, який вам потрібен для вирішення ... Але я відредагую своє повідомлення, щоб запропонувати вашу версію, якщо формат введення буде більше безкоштовно.
Дада

2

PHP, 50 байт

<?=strlen(preg_filter('/.*[^1]/','',join($argv)));

Дивно, що моя перша спроба з регулярним виразом виявилася коротшою, ніж моя з масивами ...
Використовуйте як:

php tt.php 1 1 0 1 1

2

Рубін 37 32 байти

->n{n.size-1-(n.rindex(!0)||-1)}

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

Він використовується !0як хибний, так як 0 - тривалі значення у Ruby. rindexзнаходить останній індекс значення в масиві.

Використання :

boolean_list = [true, false, false, true]
->n{n.size-1-(n.rindex(!0)||-1)}[boolean_list]

Повертає 1


Якби мені було дозволено передавати рядок 0s та 1s як параметри командного рядка (що не так, як ruby ​​представляє списки булевих значень), я міг би зменшити його до 24:

$*[0]=~/(1*)\z/;p$1.size

При цьому використовуються регулярні вирази та друкується довжина рядка, повернутого регулярним виразом /(1*)\z/, де \zє кінець рядка. $*[0]є першим переданим аргументом і являє собою рядок 0s і 1s.

Використання:

trailing_truths.rb 011101

Повертає 1.


1
Після того, як у вас є індекс останнього помилкового значення, навіщо вам знову отримувати елементи з масиву?
Лі

Ти маєш рацію, я ні. Дякую. 5 байт вимкнено!
IMP1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.