Мій пиріг був розбитий?


43

Напишіть програму або функцію, яка містить непорожній список натуральних чисел. Ви можете припустити, що він введений у прийнятному зручному форматі, наприклад, "1 2 3 4"або [1, 2, 3, 4].

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

Наприклад, пиріг для 1 2 3 4:

1 2 3 4 приклад

Питання, на яке повинен відповісти ваш код, таке: чи кругова діаграма колись поділена ? Тобто, чи існує колись ідеально пряма лінія з однієї сторони кола до іншої, розділяючи її симетрично на два?

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

У 1 2 3 4прикладі є бісекція між, 4 1і 2 3таким чином вихід був би правдивим.

Але для введення 1 2 3 4 5немає бісектриси, тому вихід буде хибним:

1 2 3 4 5 приклад

Додаткові приклади

Впорядкування чисел по-різному може видалити бісектриси.
наприклад 2 1 3 4→ фальш:

2 1 3 4 приклад

Якщо у вхідному списку є лише одне число, пиріг не розбивається.
наприклад 10→ фальш:

10 приклад

Може бути кілька бісектрис. Поки є більше нуля, вихід є правдоподібним.
наприклад 6 6 12 12 12 11 1 12→ truthy: (тут є три бісектриси)

6 6 12 12 12 11 1 12 приклад

Бісекції можуть існувати, навіть якщо вони не візуально очевидні.
наприклад 1000000 1000001→ фальш:

1000000 1000001 приклад

наприклад 1000000 1000001 1→ truthy:

1000000 1000001 1 приклад

(Дякуємо nces.ed.gov за створення пирогів.)

Випробування

Truthy
1 2 3 4
6 6 12 12 12 11 1 12
1000000 1000001 1
1 2 3
1 1
42 42
1 17 9 13 2 7 3
3 1 2
10 20 10

Falsy
1 2 3 4 5
2 1 3 4
10
1000000 1000001
1
1 2
3 1 1
1 2 1 2 1 2
10 20 10 1

Оцінка балів

Виграє найкоротший код у байтах. Тирбейкер - це відповідь раніше.


30
Я вважаю, ви маєте на увазі пиріг, який вирізали?
Алекс А.

@HelkaHomba, чи можете ви переставити сектори, щоб вони працювали, і це те, що ви мали на увазі під "упорядкуванням чисел по-різному, можуть видалити бісектриси"?
Соломон Учко

@SolomonUcko Ви можете не переставляти сектори.
Хобі Кальвіна

1
Фактично слід оцінити лише [2 1 3 4] помилкових випадків. Інші помилкові випадки легко відкидаються, оскільки їх сума непарна (або їх довжина <2).
Бенні Джобіган

Відповіді:


12

J, 18 байт

5 байт завдяки Деннісу.

+/e.[:,/2*+/\-/+/\

@HelkaHomba : Ні.

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

>> f =: +/e.[:,/2*+/\-/+/\
>> f 6 6 12 12 12 11 1 12
<< 4
>> f 10 20 10 1
<< 0

Безумовно

black_magic  =: +/\-/+/\
doubled_bm   =: 2 * black_magic
flatten      =: ,/
sum          =: +/
is_member_of =: e.
f =: sum is_member_of monadic flatten doubled_bm

Попередня 23-байтна версія:

[:+/[:+/+/=+:@-/~@(+/\)

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

>> f =: [:+/[:+/+/=+:@-/~@(+/\)
>> f 6 6 12 12 12 11 1 12
<< 4
>> f 10 20 10 1
<< 0

Безумовно

black_magic =: -/~@(+/\)
double      =: +:
equals      =: =
sum         =: +/
monadic     =: [:
of          =: @
f =: monadic sum monadic sum (sum equals double of black_magic)

Пояснення

Сума всіх підрядків обчислюється black_magic. +/\Обчислення часткових сум.

Наприклад, a b c dстає a a+b a+b+c a+b+c+d.

-/~Потім створює таблицю віднімання , заснований на вході, так що x y zстає:

x-x x-y x-z
y-x y-y y-z
z-x z-y z-z

При застосуванні до a a+b a+b+c a+b+c+dцього результатом буде:

    0  -b -b-c -b-c-d
    b   0   -c   -c-d
  b+c   c    0     -d
b+c+d c+d    d      0

Це підраховувало суми всіх підрядків, які не містять a.

Цього гарантується достатньо, оскільки якщо одна бісекція містить a, інша бісекція не міститиме, aа також не обернеться.


3
З деякою реструктуризацією ви можете дістатись до 13 байт:+/e.&,2*+/\\.
Zgarb

10

Желе , 9 8 байт

Ḥ+\©_Sf®

Поверніть не порожній список (тризубний) або порожній список (фальшивий). Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Як це працює

Ḥ+\©_Sf®  Main link. Argument: A (list)

Ḥ         Double all integers in A.
 +\       Take the cumulative sum of 2A.
   ©      Copy; store the result in the register.
    _S    Subtract the sum of A from each partial sum of 2A.
      f®  Filter; intersect this list with the list in the register.

7

Джулія, 34 30 29 байт

!x=sum(x)∈cumsum!(x,2x).-x'

Дякуємо @GlenO за те, що виграли 1 байт!

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

Як це працює

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

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


15
Подивимось, як Денніс дає 5 відповідей, перш ніж хтось дасть.
Хобі Кальвіна

6

Python 2, 64 байти

f=lambda l,s=0:l>[]and(sum(l)==s)|f(l[1:],s+l[0])|f(l,s+l.pop())

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

Денніс врятував 3 байти за допомогою pop.


Дивна альтернатива, яка дає списки:f=lambda l,s=0:l and(sum(l)==s)*l+f(l[1:],s+l[0])+f(l,s+l.pop())
xnor

5

Haskell, 41 байт

f l=elem(sum l/2)$scanr(:)[]l>>=scanl(+)0

Ідея полягає у тому, щоб перевірити, чи існує підспис l, сума якого дорівнює sum l/2. Ми формуємо суми цих списків як scanr(:)[]l>>=scanl(+)0. Давайте розглянемо, як це працюєl=[1,2,3]

>> scanr(:)[]l
[[1,2,3],[2,3],[3],[]] 
-- the suffixes of l

>> scanl(+)0 [2,3,4]
[0,2,5,9]
-- the cumulative sums of the input

>> scanr(:)[]l>>=scanl(+)0
[0,1,3,6,0,2,5,0,3,0]
-- the cumulative sums of the suffixes of l, flattened to a single list

Старі 43 байти:

f l|c<-scanl1(+)l=elem(sum l/2)$(-)<$>c<*>c

Формує список cсукупних сум. Потім перевіряють, чи відрізняються дві ці суми sum l/2, перевіряючи, чи є елементом списку відмінностей (-)<$>c<*>c.


4

Pyth, 10 9 байт

}sQmysd.:

Перевірте його в компіляторі Pyth .

Як це працює

       .:  Generate the list of all adjacent sublists.
   m       Map over the result:
     sd       Add the integers of the sublist.
    y         Double the sum.
 sQ        Compute the sum of the input.
}          Check if it belongs to the list of doubled sublist sums.

4

Власне, 21 байт

;Σ@2*;lR@τ╗`╜V♂Σi`Míu

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

Ця програма виводить значення 0для помилкових випадків та додатне ціле число для справжніх випадків.

Пояснення:

;Σ@2*;lR@τ╗`╜V♂Σi`Míu
;Σ                     sum of copy of input
  @2*                  double values in other copy
     ;lR               copy, range(1, len(input)+1)
        @τ             append other copy to itself
          ╗            save in reg0
           `╜V♂Σi`M    map: generate cyclic cumulative sums
                   íu  1-based index of sum of input (0 if not found)

Неконкурентна версія, 10 байт

;Σ@2*σ;)-∩

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

Ця програма виводить порожній список для помилкових випадків і не порожній список в іншому випадку. По суті це порт відповіді Денніса Желе . Це неконкурентоспроможне, оскільки сукупна сума та функціоналізація різної різниці після закінчення завдання

Пояснення:

;Σ@2*σ;)-∩
;Σ          sum of copy of input
  @2*       multiply values in other copy by 2
     σ;     two copies of cumulative sum
       )-   subtract sum of input from each element in one copy
         ∩  set intersection with other copy

4

Python 2, 76 74 70 66 байт

def f(x):n=sum(x);print n in[2*sum(x[k/n:k%n])for k in range(n*n)]

Дякуємо @xnor за те, що ви зіграли 4 8 байт!

Перевірте це на Ideone . (більші тестові випадки виключені)


Я зрозумів, що ти можеш n=sum(x)зробити n in ...; використовувати більше значення для n. це не завадить .
xnor

О, це розумно. Дякую!
Денніс

3

MATL , 10 байт

EYst!-Gs=z

Вихід - кількість бісектрис.

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

Пояснення

Той самий підхід, як і у відповіді Джуніса Джулії .

E       % Implicit input. Multiply by 2 element-wise 
Ys      % Cumulative sum 
t!-     % Compute all pairwise differences. Gives a 2D array 
Gs      % Sum of input 
=       % Test for equality, element-wise 
z       % Number of nonzero elements. Implicit display 

3

Рубі, 60 53 байти

->a{a.any?{r=eval a*?+;a.rotate!.any?{|i|0==r-=2*i}}}

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


2

JavaScript (ES6), 83 байти

a=>a.map(_=>a.slice(--n).map(m=>s.push(t+=m),t=0),s=[],n=a.length)&&s.includes(t/2)

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


2

Діалог APL, 12 байт

+/∊2×+\∘.-+\

Перевірте його за допомогою TryAPL .

Як це працює

+/∊2×+\∘.-+\  Monadic function train. Right argument: y (vector)

     +\   +\  Yield the cumulative sum of y.
       ∘.-    Compute all differences of all partial sums.
              This computes the sums of all adjacent subvectors of y that do not
              contain the first value, their negatives, and 0's in the diagonal.
   2×         Multiply all differences by 2.
+/            Yield the sum of y.
  ∊           Test for membership.

2

Python 2 , 47 байт

k=t=1
for x in input():t<<=x;k|=t*t
print k&k/t

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

Я повернувся через 2,75 років, щоб перемогти своє старе рішення більш ніж на 25%, використовуючи новий метод.

Ця 1-байтна довша версія трохи зрозуміліша.

k=t=0
for x in input():t+=x;k|=4**t
print k&k>>t

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

Ідея полягає у збереженні набору сукупних сум tяк бітів k, встановлення біт, 2*tщоб вказати, що tце сукупна сума. Тоді ми перевіряємо, чи відрізняються будь-які дві сукупні суми вдвічі від суми списку (остаточного t) шляхом зміщення kцього біта та &з побітним розрядом на оригінал, щоб побачити результат ненульовий (truthy).


1

APL, 25 символів

Припустимо, що список наведено в X ← 1 2 3 4.

(+/X)∊∘.{2×+/⍺↑⍵↓X,X}⍨⍳⍴X←⎕

Пояснення:

Спочатку зауважте, що APL оцінює форму праворуч ліворуч. Тоді:

  • X←⎕ приймає введення користувача та зберігає його в X

  • ⍴X дає довжину X

  • ⍳⍴X числа від 1 до ⍴X

  • Аргумент " і в" {2×+/⍺↑⍵↓X,X}- це лівий і правий аргумент діадичної функції, яку ми визначаємо всередині дужок.

    • Тепер для ⍺↑⍵↓X,Xчастини: X,Xпросто з'єднайте X із самим собою; і беруть і кидають.
    • +/зменшує / згортає +список праворуч

    Отже 2 {2×+/⍺↑⍵↓X,X} 1= 2×+/2↑1↓X,X= 2×+/2↑1↓1 2 3 4 1 2 3 4=

    = 2×+/2↑2 3 4 1 2 3 4= 2×+/2 3= 2×5= 10.

  • ∘.brace⍨idxпросто idx ∘.brace idx. ( це діагональна карта; ∘.це зовнішній добуток)

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

     4  6  8  2
    10 14 10  6
    18 16 14 12
    20 20 20 20
    

    Останнє, що ми повинні зробити, це перевірити, чи є сума Xдесь у цій матриці.

  • Що ми робимо (+/X)∊matrix.


1

C, 161 145 129 байт

  • збережено кілька байт завдяки @LeakyNun
  • збережено кілька байт завдяки @ceilingcat
i;j;k;t;r;s;f(x,n)int*x;{for(t=i=k=r=0;i<n;)t+=x[i++];for(;++k<n;i=n)for(;i--;r|=2*s==t)for(s=0,j=i;j<i+k;)s+=x[j++%n];return r;}

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

int f(int*x,int n)
{
    int t=0;

    for(int i=0;i<n;i++)
    {
        t += x[i];
    }

    for(int k=1;k<n;k++) // subset-size
    {
        for(int i=0,s;i<n;i++) // where to start
        {
            s=0;

            for(int j=i;j<i+k;j++) // sum the subset
            {
                s+=x[j%n];
            }

            if(2*s==t) return 1; // TRUE
        }
    }

    return 0; // FALSE
}

Може бути , ви можете заощадити кілька байт, переміщаючи оголошення змінних на перший рівень, і зміни i<n;i++в i++<n(хоча , можливо , доведеться мати справу з деякими зрушеннями.
Дірявий Nun

0

Хаскелл, 68 байт

f l|x<-[0..length l]=any(sum l==)[2*(sum$take a$drop b l)|a<-x,b<-x]

Функція fспочатку створює перелік сум усіх можливих фрагментів даного списку. Потім вона порівнює зі загальною сумою елементів списку. Якщо ми отримаємо в якийсь момент половину від загальної суми, то ми знаємо, що у нас є бісекція. Я також використовую той факт, що якщо ви takeабо dropкілька елементів, ніж їх у списку, Haskell не видає помилку.


0

Математика, 48 байт

!FreeQ[Outer[Plus,#,-#],Last@#/2]&@Accumulate@#&

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

Outer[Plus, #, -#], коли діє на Accumulate@#(який, у свою чергу, діє на вхідному списку, даючи список послідовних підсумків), створює по суті ту саму таблицю, що і внизу відповіді Лікі Нун.

!FreeQ[..., Last@#/2]перевіряє, (Last@#)/2є НЕ відсутні в результуючій таблиці, і Last@#є останнім з послідовних сум, тобто сума всіх елементів списку вводу.

Якщо ця відповідь дещо цікава, це не через новий алгоритм, а більше про хитрощі, характерні для Mathematica; наприклад, !FreeQце приємно, порівняно з тим MemberQ, що для нього не потрібно згладжування таблиці, яку він перевіряє, і це економить байт.


Я думаю, що це !FreeQ[2Tr/@Subsequences@#,Tr@#]&має працювати, але я не матиму доступних 10.4 для тестування протягом наступних 10 днів.
Мартін Ендер

@MartinEnder Це, звичайно, схоже, що це спрацювало б, але я на 10.2, так що у мене є
LLlAMnYP

0

APL (NARS), символи 95, байти 190

{1≥k←≢w←⍵:0⋄s←+/⍵⋄∨/{s=2×s-+/⍵}¨↑¨{⍵⊂w}¨{(k⍴2)⊤⍵}¨{1≥≢⍵:⍵⋄⍵,∇{(1+2×(↑⍵))×2*0..¯2+≢⍵}⍵}2*0..k-1}

Розглянемо один масив введення 4-х елементів: 1 2 3 4. Як ми можемо вибрати корисний для цього вправ розділ цього набору? Якщо хтось вважає, що розділ цих 4 елементів, який ми можемо використовувати, описаний у двійковому номері зліва:

0001,0010,0100,1000 2^(0..4) 1 2 4  8 
0011,0110,1100,                3 6 12
0111,1110,                       7 14
1111                               15

(1001 або 1011 екв. Може бути в цьому наборі, але вже є 0110 та 0100 екк.), Тому одна шапка просто написати одну функцію, яка з числа елементів вхідного масиву будує ці двійкові числа ... було б:

c←{1≥≢⍵:⍵⋄⍵,∇{(1+2×(↑⍵))×2*0..¯2+≢⍵}⍵}

що з введення 1 2 4 8 [2 ^ 0..lenBytesArgument-1] знайдіть 3 6 12, 7 14, 15; тому знайдіть двійкові ці числа та за допомогою них знайдіть правильні розділи вхідного масиву ... Я перевірив функцію c лише для цього вхідного 4 елемента, але, здається, це нормально для іншої кількості елементів ...

тест:

  f←{1≥k←≢w←⍵:0⋄s←+/⍵⋄∨/{s=2×s-+/⍵}¨↑¨{⍵⊂w}¨{(k⍴2)⊤⍵}¨{1≥≢⍵:⍵⋄⍵,∇{(1+2×(↑⍵))×2*0..¯2+≢⍵}⍵}2*0..k-1}
  f¨(1 2 3 4)(6 6 12 12 12 11 1 12)(1000000 1000001 1)(1 2 3)(1 1)(42 42)
1 1 1 1 1 1 
  f¨(1 2 3 4 5)(2 1 3 4)(,10)(1000000 1000001)(,1)(1 2)(3 1 1)
0 0 0 0 0 0 0 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.