Minha torta foi cortada?

43

Escreva um programa ou função que inclua uma lista não vazia de números inteiros positivos. Você pode assumir que é inserido em um formato conveniente razoável, como "1 2 3 4"ou [1, 2, 3, 4].

Os números na lista de entrada representam as fatias de um gráfico de pizza completo , em que cada tamanho de fatia é proporcional ao número correspondente e todas as fatias são organizadas em torno do gráfico na ordem fornecida.

Por exemplo, a torta para 1 2 3 4é:

1 2 3 4 exemplo

A pergunta que seu código deve responder é: O gráfico de pizza é dividido em duas partes ? Ou seja, existe sempre uma linha perfeitamente reta de um lado do círculo para o outro, dividindo-o simetricamente em dois?

Você precisa mostrar um truthy valor se houver pelo menos uma bissetriz e saída de um Falsas valor se não houver nenhum .

No 1 2 3 4exemplo, há uma bissecção entre 4 1e, 2 3portanto, a saída seria verdadeira.

Mas, para entrada, 1 2 3 4 5não há bissetor, portanto a saída seria falsa:

1 2 3 4 5 exemplo

Exemplos adicionais

Organizar números de maneira diferente pode remover os bissetores.
por exemplo 2 1 3 4→ falsy:

2 1 3 4 exemplo

Se apenas um número estiver na lista de entrada, a torta não será dividida em partes.
por exemplo 10→ falsy:

10 exemplo

Pode haver vários bissetores. Desde que haja mais de zero, a saída é verdadeira.
por exemplo 6 6 12 12 12 11 1 12→ truthy: (existem 3 bissetores aqui)

6 6 12 12 12 11 1 12 exemplo

Podem existir bisseções mesmo que não sejam visualmente óbvias.
por exemplo 1000000 1000001→ falsy:

1000000 1000001 exemplo

por exemplo 1000000 1000001 1→ verdade:

1000000 1000001 1 exemplo

(Agradecemos a nces.ed.gov por gerar os gráficos de pizza.)

Casos de teste

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

Pontuação

O código mais curto em bytes vence. O desempatador é a resposta anterior.

Hobbies de Calvin
fonte
30
Eu acredito que você quer dizer torta seccionada?
Alex A.
@HelkaHomba, você pode reorganizar os setores para fazê-lo funcionar e é isso que você quis dizer com "organizar números de maneira diferente para remover bissetores"?
Solomon Ucko,
@SolomonUcko Você não pode reorganizar os setores.
Hobbies de Calvin
1
Somente [2 1 3 4] dos casos falsos deve ser realmente avaliado. Os outros casos falsos são facilmente rejeitados porque sua soma é ímpar (ou seu comprimento é <2).
precisa saber é o seguinte

Respostas:

12

J, 18 bytes

5 bytes graças a Dennis.

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

@HelkaHomba : Não.

Uso

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

Ungolfed

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

Versão anterior de 23 bytes:

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

Uso

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

Ungolfed

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

Explicação

A soma de todas as substrings é calculada pelo black_magic. O +/\calcular as somas parciais.

Por exemplo, a b c dtorna-se a a+b a+b+c a+b+c+d.

Em -/~seguida, constrói uma tabela de subtração com base na entrada, x y ztornando-se:

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

Quando aplicado a a+b a+b+c a+b+c+d, o resultado seria:

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

Isso calculou as somas de todas as substrings que não contêm a.

Isso garante que é suficiente, pois se uma bisseção contiver a, a outra não conterá ae também não será contornada.

Freira Furada
fonte
3
Com algumas reestruturações, você pode obter 13 bytes:+/e.&,2*+/\\.
Zgarb 4/16
10

Geléia , 9 8 bytes

Ḥ+\©_Sf®

Retornar uma lista não vazia (verdade) ou uma lista vazia (falsy). Experimente online! ou verifique todos os casos de teste .

Como funciona

Ḥ+\©_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.
Dennis
fonte
7

Julia, 34 30 29 bytes

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

Graças a @GlenO por jogar fora 1 byte!

Experimente online!

Como funciona

Depois de armazenar a soma acumulada de 2x em x , subtraímos o vetor de linha x ' do vetor de coluna x , produzindo a matriz de todas as diferenças possíveis. Essencialmente, isso calcula as somas de todas as sub-matrizes adjacentes de x que não contêm o primeiro valor, seus negativos e 0 na diagonal.

Finalmente, testamos se a soma da matriz original x pertence à matriz gerada. Se for esse o caso, a soma de pelo menos uma das sublistas adjacentes é igual à metade da soma da lista inteira, o que significa que há pelo menos uma bissetriz.

Dennis
fonte
15
Vamos ver como Dennis dá 5 respostas antes que mais alguém dê uma.
Passatempos de Calvin
6

Python 2, 64 bytes

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

Recursivamente tenta remover elementos da frente ou do final até que a soma do que resta seja igual à soma do que foi excluído, que é armazenado s. Leva tempo exponencial no comprimento da lista.

Dennis salvou 3 bytes com pop.

xnor
fonte
Uma alternativa estranha que fornece listas:f=lambda l,s=0:l and(sum(l)==s)*l+f(l[1:],s+l[0])+f(l,s+l.pop())
xnor 4/16
5

Haskell, 41 bytes

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

A idéia é verificar se existe uma sub-lista lcuja soma é igual sum l/2. Geramos as somas desses sublistas como scanr(:)[]l>>=scanl(+)0. Vamos ver como isso funciona coml=[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 bytes antigos:

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

Gera a lista cde somas cumulativas. Em seguida, verifica se duas dessas somas diferem sum l/2verificando se é um elemento da lista de diferenças (-)<$>c<*>c.

xnor
fonte
4

Pitão, 10 9 bytes

}sQmysd.:

Teste-o no Pyth Compiler .

Como funciona

       .:  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.
Dennis
fonte
4

Na verdade, 21 bytes

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

Experimente online!

Este programa imprime um 0para casos falsos e um número inteiro positivo para casos verdadeiros.

Explicação:

;Σ@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)

Versão não concorrente, 10 bytes

;Σ@2*σ;)-∩

Experimente online!

Este programa gera uma lista vazia para casos falsos e uma lista não vazia caso contrário. É essencialmente um porto da resposta da geléia de Dennis . Não é concorrente porque a soma cumulativa e a funcionalidade de diferença vetorizada pós-desafio.

Explicação:

;Σ@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
Mego
fonte
4

Python 2, 76 74 70 66 bytes

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

Graças a @xnor por jogar fora 4 8 bytes!

Teste em Ideone . (casos de teste maiores excluídos)

Dennis
fonte
Eu percebi que você pode n=sum(x)fazer n in ...; não custa usar um valor maior para n.
Xnor
Ooh, isso é inteligente. Obrigado!
Dennis
3

MATL , 10 bytes

EYst!-Gs=z

A saída é o número de bissetores.

Experimente online!

Explicação

A mesma abordagem da resposta de Dennis para Julia .

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 
Luis Mendo
fonte
3

Rubi, 60 53 bytes

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

Gera todas as partições possíveis realizando todas as rotações da matriz de entrada e, em seguida, todas as fatias de comprimento 1 .. n, onde né o tamanho da matriz de entrada. Em seguida, verifica se existe alguma partição com uma soma metade da soma total da matriz de entrada.

Ventero
fonte
2

JavaScript (ES6), 83 bytes

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

Gera todas as somas possíveis e verifica se metade da última soma (que é a soma de toda a lista) aparece na lista. (Gerar as somas na ordem um pouco estranha para organizar a soma que eu preciso ser economiza 4 bytes pela última vez.)

Neil
fonte
2

Dyalog APL, 12 bytes

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

Teste com o TryAPL .

Como funciona

+/∊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.
Dennis
fonte
2

Python 2 , 47 bytes

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

Experimente online!

Voltei 2,75 anos depois para vencer minha solução antiga em mais de 25% usando um novo método.

Esta versão mais longa de 1 byte é um pouco mais clara.

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

Experimente online!

A idéia é armazenar o conjunto de somas cumulativas tcomo bits de k, definindo bit 2*tpara indicar que té uma soma cumulativa. Em seguida, verificamos se duas somas cumulativas diferem pela metade da soma da lista (final t), deslocando-se ktanto assim e fazendo bit a bit &com o original para ver se o resultado é diferente de zero (verdade).

xnor
fonte
1

APL, 25 caracteres

Supondo que a lista seja apresentada em X ← 1 2 3 4.

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

Explicação:

Primeira nota que o APL avalia o formulário da direita para a esquerda. Então:

  • X←⎕ pega a entrada do usuário e a armazena X

  • ⍴X dá o comprimento de X

  • ⍳⍴X os números de 1 a ⍴X

  • The e in {2×+/⍺↑⍵↓X,X}são o argumento esquerdo e direito de uma função diádica que estamos definindo dentro do aparelho.

    • Agora, para a ⍺↑⍵↓X,Xparte: X,Xapenas concatena X consigo mesmo; e são pegar e largar.
    • +/reduz / dobra +a lista à sua direita

    Então 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é justo idx ∘.brace idx. ( é o mapa diagonal; ∘.é o produto externo)

    Portanto, isso nos dá uma matriz ⍴Xby ⍴Xque contém duas vezes a soma de todas as sublistas conectadas.

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

    A última coisa que precisamos fazer é verificar se a soma de Xestá em algum lugar dentro dessa matriz.

  • Com o que fazemos (+/X)∊matrix.
user2070206
fonte
1

Braquilog , 6 bytes

sj+~+?

Experimente online!

Resultados por sucesso ou falha, impressão true.ou false.se executados como um programa.

s         A contiguous sublist of the input
 j        with all of its items duplicated
  +       sums to
   ~+     the sum of the elements of
     ?    the input.
String não relacionada
fonte
1

C, 161 145 129 bytes

  • economizou alguns bytes graças a @LeakyNun
  • economizou alguns bytes graças a @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;}

Tentativa sem golfe online

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
}
Khaled.K
fonte
Talvez você pode economizar alguns bytes movendo as declarações das variáveis para o primeiro nível, e mudando i<n;i++para i++<n(embora você pode precisar para lidar com algumas compensações.
Leaky Nun
0

Haskell, 68 bytes

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

A função fprimeiro cria uma lista das somas de todas as fatias possíveis da lista fornecida. Em seguida, ele se compara à soma total dos elementos da lista. Se chegarmos a algum ponto da metade da soma total, sabemos que temos uma bissecção. Também estou usando o fato de que, se você takeou dropmais elementos do que existem na lista, Haskell não gera um erro.

flawr
fonte
0

Mathematica, 48 bytes

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

Função anônima, semelhante em ação às inúmeras outras respostas.

Outer[Plus, #, -#], quando agir em Accumulate@#(que por sua vez atua na lista de entrada, fornecendo uma lista de totais sucessivos) gera essencialmente a mesma tabela, como na parte inferior da resposta da freira furtiva.

!FreeQ[..., Last@#/2]verifica se não(Last@#)/2 está ausente da tabela resultante e é o último dos totais sucessivos, ou seja, a soma de todos os elementos da lista de entrada.Last@#

Se essa resposta for um tanto interessante, não é por causa de um novo algoritmo, mas mais pelos truques específicos do Mathematica; por exemplo, !FreeQé bom, comparado a MemberQ, já que não requer um achatamento da tabela que verifica e salva um byte.

LLlAMnYP
fonte
Eu acho que !FreeQ[2Tr/@Subsequences@#,Tr@#]&deve funcionar, mas não terei o 10.4 disponível para testá-lo pelos próximos 10 dias.
Martin Ender
@MartinEnder Certamente parece que ele iria trabalhar, mas eu estou em 10,2, de modo que é o que eu tenho
LLlAMnYP
0

APL (NARS), caracteres 95, bytes 190

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

Considere uma matriz de entrada de 4 elementos: 1 2 3 4. Como podemos escolher o útil para esta partição de exercício desse conjunto? Alguns acham que a partição desses 4 elementos que podemos usar está descrita no número binário à esquerda:

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

(1001 ou 1011 ecc pode estar nesse conjunto, mas já temos 0110 e 0100 ecc), portanto, um chapéu apenas para escrever uma função que, a partir do número de elemento da matriz de entrada, construa esses números binários ... seria:

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

que da entrada 1 2 4 8 [2 ^ 0..lenBytesArgument-1] encontre 3 6 12, 7 14, 15; então encontre binário desses números e use-os para encontrar as partições certas da matriz de entrada ... Testei a função c apenas para essa entrada 4 elementos, mas parece que está ok para outro número de elementos ...

teste:

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