Фальсифікувати короткі істини


28

Знайдіть найдовший пробіг істини в списку булей. Поверніть той самий список із фальсифікованими усіма іншими підписами.

Введення-виведення

Список; будь-який звичайний формат (наприклад, обмежений список у вигляді рядка).

Деталі

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

Якщо ви будете зрізати для найдовшого пробігу, продовжуйте виконувати всі зав'язувальні прогони і фальсифікуйте всі коротші пробіги.

Приклади

input ↦ output
1,0,1,0,1 ↦ 1,0,1,0,1
1,1,0,1,1,0,1 ↦ 1,1,0,1,1,0,0
1,1,0,1,1,1,0,1,1 ↦ 0,0,0,1,1,1,0,0,0
1,1,1 ↦ 1,1,1
0,0,1 ↦ 0,0,1
0,0 ↦ 0,0
1,1,1,0,0,0,1,1,1,1,0,1,0,0,1,1,0,1,1,1,1,0,0,1,0 ↦ 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0

(безпосередньо з /programming//q/37447114 )

Відповіді:


19

Желе , 8 байт

ṣ0¬¬M¦j0

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

Як це працює

ṣ0¬¬M¦j0  Main link. Argument: A (list of Booleans)

ṣ0        Split at zeroes. This leaves a 2D list of ones.
  ¬       Negate each 1, replacing it with 0.
     ¦    Conditional application:
    M       Yield all maximal indices.
            In lexicographical list comparison, a shorter list of zeroes is less
            than a longer one, so this identifies the longest runs.
   ¬        Negate the items in those lists, changing zeroes back to ones.
      j0  Join, separating by single zeroes.

23
Боже ... ця мова ...
AdmBorkBork

11

Haskell, 59 , 58 , 55 , 64 байт

import Data.List
((=<<)=<<(=<<)(<$).(==).maximum.([1<2]:)).group

Примітка, це працює в будь-якому списку значень, де falsy < truthy. Так False/True, 0/1, 'f'/'t'і т.д.

Примітка:

Як зазначали декілька людей (включаючи @proud haskellerі @nimi), попередня версія зазнала невдачі у списку всіх фальшивих значень. Додавання .([1<2]:)зафіксувало це, як запропонував @proud haskeller. Я покидаю пояснення тим самим, тому що я думаю, що це все ще має сенс. Якщо хтось коментує, запитуючи пояснення правки, я відредагую.

Пояснення:

Я спершу десугар без цього group, а потім додаю його назад. По-перше, я вважаю, що слова часто легші на очі, ніж символи, тому я зроблю кілька підстановок. (Зверніть увагу, що =<<це "класний", тому він застосовується по-різному для списків і функцій. Я називаю bindверсію =<<функцій.)

bind :: (a -> b -> c) -> (b -> a) -> b -> c
bind k f = k =<< f
bind k f = \ r -> k (f r) r

f = ((=<<)=<<(=<<)(<$).(==).maximum)
f = ((bind) concatMap (bind)(<$).equals.maximum)
f = (bind concatMap (bind (<$) . equals . maximum))
f = bind concatMap ((bind (<$)) . equals . maximum))
f = bind concatMap ((\f r -> (<$) (f r) r) . equals . maximum))
f = bind concatMap ((\f r -> (f r) <$ r) . equals . maximum)
f = bind concatMap ((\g r -> (g r) <$ r) . equals . maximum)
f = (\h r -> concatMap (h r) r) ((\g r -> (g r) <$ r) . equals . maximum)
f = \r -> concatMap (((\g r -> (g r) <$ r) . equals . maximum) r) r
f = \r -> concatMap (((\g r -> (g r) <$ r) . equals) (maximum r)) r
f = \r -> concatMap (((\g s -> (g s) <$ s)) (equals (maximum r))) r
f = \r -> concatMap (((\s -> ((equals (maximum r)) s) <$ s))) r
f = \r -> concatMap (\s -> (s == (maximum r)) <$ s) r

f . group = ((=<<)=<<(=<<)(<$).(==).maximum).group
f . group = \r -> concatMap (\s -> (s == (maximum (group r))) <$ s) (group r)

Останні деталі , які x <$ listзамінюють кожен елемент listз xі group listрозбивають listна шматки рівних елементів. Отже group [1, 1, 2, 3, 3, 3] == [[1, 1], [2], [3, 3, 3]].

Підсумовуючи все це, функція розбиває список значень на групи лише істинних та групи лише хибних. Потім для кожної групи замініть кожен елемент результатом оператора this is the biggest group(найбільша група trues буде найбільшою) і об'єднайте групи.

Чотири байти, збережені користувачем @Zgarb


1
Я думаю , ви можете замінити (\y->(maximum g==y)<$y)з ((<$)=<<(==maximum g)). Я не перевіряв цього.
Згарб

@ Zgarb Я щойно опрацював це з декларації екземпляра, і він працює. Спасибі.
Майкл Кляйн

3
Ще краще: замініть все визначення fфункцією без точок ((=<<)=<<(=<<)(<$).(==).maximum).group. Економить три байти і зовсім не читається!
Згарб

@Zgarb: Класно! У цей момент b=(=<<);b b(b(<$).(==).maximum).groupще один байт коротший. Я ніколи не бачив нічого подібного раніше в Haskell golf :)
Лінн

1
Якщо я не помиляюся, ви можете це виправити, вставивши (:[t])перед максимумом чи чимось подібним
гордий haskeller

6

Сітківка, 47 43 36

0
!
T`p`0`\b(1+)\b(?<=(?=.*1\1).*)|!

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

Дякуємо msh210 для гри в гольф на 4 байти!

Також велика подяка Мартіну за 7 байт!

Пояснення:

0
!

Замініть всі 0s на !s. Це робиться для того, щоб збігати групи з 1s коротше, як зараз, 1!і між ними !1буде слово кордону ( \b), яке також відповідає початку або кінцю рядка.

T`p`0`

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

\b(1+)\b(?<=(?=.*1\1).*)|!

Цей регулярний вираз відповідає групам 1s, які оточені нулями, але не можуть відповідати 1послідовним самим у будь-якому місці рядка. Це немаксимальні групи, які будуть фальсифіковані. Крім того, це також відповідає !символам, які ми додали, щоб перетворити їх назад в 0s.


5

MATL, 14 байт

Y'yy*X>y=b*wY"

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

Модифікована версія з усіма тестовими кейсами

Пояснення

        % Implicitly grab the input as an array
Y'      % Perform run-length encoding of the input. Yields an array of values and an array
        % of run-lengths
yy      % Copy these outputs
*       % Multiply the values (booleans) by the run-lengths. This will zero-out all
        % zero-valued runs so we don't consider them when computing the longest run.
X>      % Compute the longest run of 1's
y       % Copy the run lengths vector
=       % Determine which runs are the same length as the longest run of ones
b*      % Bubble-up the values from the run-length encoding and multiply element-wise
        % With this boolean. This substitutes all 1's that are not in the longest run
        % of ones with 0's
w       % Flip the run-lengths and values on the stack
Y"      % Perform run-length decoding using these substituted values
        % Implicitly display the resulting boolean

4

Python 2, 62 байти

lambda s:'0'.join(`1-(t+'1'in s)`*len(t)for t in s.split('0'))

Перевірте це на Ideone .

Як це працює

s.split('0')розбиває вхідний рядок s на прогони нульових або більше 1 's

Для кожного запуску t ми перевіряємо, чи t+'1'є підрядком s .

  • Якщо він є, запуск не є максимальним, t+'1'in sповерніть True , 1-(t+'1'in s)поверніть 1 - True = 0, а запуск замінюється на пробіг 0 s однакової довжини.

  • Якщо це не так, то пробіг є максимальним, t+'1'in sповернення False , 1-(t+'1'in s)повернення 1 - False = 1, і запуск замінюється на пробіг 1 s однакової довжини, тобто сам по собі.

Нарешті, '0'.joinвідновлює всі видалені " 0 ".


3

J, 25 байт

[:(}.=>./)@;0<@(*#);.1@,]

Це монадійне дієслово, яке приймає і повертає масив 0-1. Використовуйте його так:

   f =: [:(}.=>./)@;0<@(*#);.1@,]
   f 1 1 0 1 1 1 0 1 1
0 0 0 1 1 1 0 0 0

Пояснення

[:(}.=>./)@;0<@(*#);.1@,]  Input is y.
            0          ,]  Prepend 0 to y, and
                   ;.1@    cut the result along occurrences of 0,
                           so that each piece begins with a 0.
               (*#)        Multiply each piece element-wise by its length,
             <@            and put it in a box.
                           Without the boxing, the pieces would go in a 0-padded array.
           ;               Join the pieces back together.
                           Now all runs of 1 have been replaced by runs of (1+length of run).
[:(      )@                Apply verb in parentheses:
   }.                        remove the prepended 0,
     =                       form the 0-1 array of equality with
      >./                    the maximum value.

Гарне використання розрізу ;..
миль

3

Pyth, 26 24 23 21 байт

M,G&HGJrgMrQ8 9qReSJJ

Тестовий набір.

  • Використання 1/0або true/falseвведення.
  • Використання true/falseна виході.

Пояснення

M,G&HGJrgMrQ8 9qReSJJ

           Q      input
          r 8     run-length encode
        gM        convert each run of 1 to their length
                  for example: [1,1,1,0,1,1] will be
                  converted to [3,3,3,0,2,2]
                  in the run-length encoded version
                  [1,1,1,0,1,1] will be [[3,1],[1,0],[2,1]]
                  [3,3,3,0,2,2] will be [[3,3],[1,0],[2,2]]
                  therefore basically [G,H] becomes [G,H and G]
                  which is what the code below does:
M,G&HG            def g(G,H): return [G,H and G]
       r      9   run-length decode
      J           store to J

               qReSJJ

                R   J   in each element of J
               q eSJ    check if equal to maximum of J

Попередній 23-байт

M,G&HGJrgMrQ8 9msqdeSJJ

Тестовий набір.

  • Використання 1/0або true/falseвведення.
  • Використання 1/0на виході.

Попередній 24-байт

Jrm,hd&edhdrQ8 9msqdeSJJ

Тестовий набір.

  • Використання 1/0або true/falseвведення.
  • Використання 1/0на виході.

Попередній 26-байт

rm?nhdeS.u&YhNQ0,hd0drQ8 9

Тестовий набір.

  • Використання 1/0або true/falseвведення.
  • Використання 1/0на виході.

Створення функції, яка викликається лише в одному місці, майже завжди є помилкою. Наприклад, ви можете замінити його на: Jr.b,N&YNrQ8)9qReSJJабо Jrm,hd*FdrQ8 9qReSJJ. Обидві версії зберігають один байт. Або йдіть ще більш шалено JrXR1*FdrQ8 9qReSJJі заощадите двох. ;-)
Якубе

2

Oracle SQL 12.1, 137 135 байт

SELECT REPLACE(REPLACE(REPLACE(:1,m,2),1,0),2,m)FROM(SELECT MAX(TRIM(COLUMN_VALUE))m FROM XMLTABLE(('"'||REPLACE(:1,0,'",0,"')||'"')));

Без гольфу

-- Replace the max value with 2
-- Then replace every 1 with 0
-- Then replace 2 with the max value
SELECT REPLACE(REPLACE(REPLACE(:1,m,2),1,0),2,m)
FROM   ( -- Split on 0 and keep the max value
         SELECT MAX(TRIM(COLUMN_VALUE))m 
         FROM XMLTABLE(('"'||REPLACE(:1,'0','",0,"')||'"'))
       );

Використовуйте введення одиночних символів. Наприклад: '1100111'


2

Математика , 46 41

1-Join@@Sign[1~Max~#-#]&[#*Tr/@#]&@*Split

Працює за списками 0та 1. Я думав, що зробив досить добре, поки не подивився на інші відповіді!


Пояснення версії 46 символів; Я буду оновлювати, коли не можу додатково покращити його.

Потрібно було пояснити цей код.
Еквівалент гольфу без коду (використовуючи форми оператора версії 10):

RightComposition[
  Split,
  Map[# Tr@# &],
  # - Max[1, #] &,
  UnitStep,
  Apply[Join]
]

Це означає, що функція складається з п’яти кроків (підфункцій), застосованих у порядку від верху до низу.

  • Split: розбийте на прогони однакових елементів: {1,1,0,1,1,0,1} ↦ {{1,1}, {0}, {1,1}, {0,0}}

  • Map[# Tr@# &]: Для кожного підсписку ( Map) помножте його ( #) на його суму (векторний слід Tr): {1,1} ↦ {2, 2}

  • # - Max[1, #] &відняти від кожного елемента максимальне значення, що з’являється в будь-якому місці списку, або один, залежно від того, що вище. (Той обробляє справу всіх нулів.)

  • UnitStep: дорівнює 0 для x <0 і 1 для x> = 0, застосованих до кожного елемента.

  • Apply[Join]: приєднайте підсписки до єдиного списку. Також може бути зроблено з Flattenабо Catenate, але, Join@@стисло кажучи, це більш коротко.


2

C, 135 129 байт

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

m,c,i,d,j;f(int*l,int s){while(i<s)c=l[i++]?c+1:0,m=c>m?c:m;while(j<s)if(l[j++])d=d+1;else if(d<m)while(d)l[j-1-d--]=0;else d=0;}

Безумовно

m,c,i;
f(int*l,int s)
{
    // obtain max
    while(i<s)
        c = l[i++] ? c+1 : 0,
        m = c>m ? c : m;

    c=0,i=0;

    // remove smaller segments
    while(i<s)
        if(l[i++]) c=c+1;
        else if(c<m) while(c) l[(i-1)-c--]=0;
        else c=0;
}

1

JavaScript (ES6), 56 байт

s=>s.replace(/1+/g,t=>t.replace(/1/g,+!~s.indexOf(t+1)))

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

Попереднє 72-байтне рекурсивне рішення:

f=s=>/11/.test(s)?f(s.replace(/1(1*)/g,"0$1")).replace(/0(1+)/g,"1$1"):s

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


"У всіх прогонах 1s замініть кожен 1 на 0, якщо існує пробіг на 1s, довший за поточний, а інший замініть на 0." Блискуче!
Патрік Робертс

1

Юлія, 51 байт

s->replace(s,r"1+",t->map(c->c-contains(s,"1"t),t))

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

Як це працює

replaceзнаходить усі запуски одного або декількох 1 -х у вхідному рядку s через регулярний вираз r"1+"і викликає лямбда, t->map(c->c-contains(s,"1"t),t)щоб визначити рядок заміни.

Лямбда відображає c->c-contains(s,"1"t)всіх символів під час руху t .

  • Якщо "1"t(конкатенація) є підрядкою s , запуск не є максимальним, containsповертає true та c-contains(s,"1"t)повертає '1' - true = '0' , замінюючи всі 1 's у цьому пробігу на 0 ' s.

  • Якщо "1"t(конкатенація) не є підрядкою s , виконання є максимальним, containsповертає false та c-contains(s,"1"t)повертає '1' - false = '1' , залишаючи запуск немодифікованим.


1

APL, 22 ч

(⊣=⌈/)∊(⊣×+/¨)(~⊂⊣)0,⎕

Англійською (справа наліво в блоках):

  • додайте 0 на вхід
  • поле, починаючи з 0
  • помножте кожне поле на його суму
  • сплющити
  • 1, якщо число дорівнює максу, 0 в іншому випадку

1

Java 8, 205 байт

Це лямбда-вираз для Function<String,String>:

s->{int x=s.length();for(String t="1",f="0";s.indexOf(t+1)>=0;t+=1){s=s.replaceAll(0+t+0,0+f+0);if(s.indexOf(t+0)==0)s=s.replaceFirst(t,f);if(s.lastIndexOf(0+t)==--x-1)s=s.substring(0,x)+f;f+=0;}return s;}

вхід / вихід - а, Stringде true представлено 1, а false - 0. Немає знаків роздільника, які розділяють значення.

код з поясненням:

inputString -> {
  int x = inputString.length();
  //starting with the truth combination "1",
  //loop until the input string does not contain the combination appended with another "1"
  //with each consecutive loop appending a "1" to the combination
  for( String truthCombo = "1", falseCombo = "0"; inputString.indexOf( truthCombo + 1 ) >= 0; truthCombo += 1 ) {
    //all instances in the input string 
    //where the combination has a "0" on either side of it
    //are replaced by "0"'s
    inputString = inputString.replaceAll( 0 + truthCombo + 0, 0 + falseCombo + 0 );
    //if the combination followed by a "0"
    //is found at the beginning of the input string
    //replace it with "0"'s
    if( inputString.indexOf( truthCombo + 0 ) == 0 )
      inputString = inputString.replaceFirst( truthCombo , falseCombo );
    //if the combination preceeded by a "0"
    //is found at the end of the input string
    //replace it with "0"'s
    if( inputString.lastIndexOf( 0 + truthCombo ) == --x - 1 )
      inputString = inputString.substring( 0, x ) + falseCombo;
    falseCombo += 0;
  }
  return inputString;
}

див. ідеон для тестових випадків


1

Clojure, 137 байт

#(let[v(map(juxt first count)(partition-by #{1}%))](mapcat(fn[t](repeat(t 1)(if(=[1(apply max(map(fn[[f c]](if(= 1 f)c 0))v))]t)1 0)))v))

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

Менше гольфу:

(def f #(let [v(map(juxt first count)(partition-by #{1}%))
              m(apply max(map(fn[[f c]](if(= 1 f)c 0))v))]
           (mapcat (fn[[f c]](repeat c(if(=[1 m][f c])1 0))) v)))

0

Perl 5, 68 байт

67, плюс 1 для -peзамість-e

y/0/ /;$_<${[sort@a]}[-1]&&y/1/0/for@a=split/\b/;$_=join"",@a;y; ;0

Очікує і друкує рядок (конкатенація) 0 і 1.

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