La mia torta è stata tagliata in due?


43

Scrivi un programma o una funzione che contiene un elenco non vuoto di numeri interi positivi. Si può presumere che sia inserito in un formato conveniente ragionevole come "1 2 3 4"o [1, 2, 3, 4].

I numeri nell'elenco di input rappresentano le sezioni di un grafico a torta completo in cui ogni dimensione della sezione è proporzionale al numero corrispondente e tutte le sezioni sono disposte attorno al grafico nell'ordine indicato.

Ad esempio, la torta per 1 2 3 4è:

1 2 3 4 esempio

La domanda alla quale il tuo codice deve rispondere è: il grafico a torta è mai diviso in due ? Cioè, c'è mai una linea perfettamente dritta da un lato del cerchio all'altro, dividendola simmetricamente in due?

È necessario generare un valore di verità se esiste almeno una bisettrice e generare un valore di falsa se non ce ne sono .

Nel 1 2 3 4esempio c'è una bisezione tra 4 1e 2 3così l'uscita sarebbe truthy.

Ma per l'input 1 2 3 4 5non c'è bisettrice quindi l'output sarebbe falso:

1 2 3 4 5 esempio

Esempi aggiuntivi

Disporre i numeri in modo diverso può rimuovere le bisettrici.
ad es. 2 1 3 4→ falsy:

2 1 3 4 esempio

Se nell'elenco di input è presente un solo numero, la torta non viene tagliata in due.
ad es. 10→ falsy:

10 esempio

Possono esserci più bisettrici. Finché ce ne sono più di zero, l'output è veritiero.
es. 6 6 12 12 12 11 1 12→ verità: (ci sono 3 bisettrici qui)

6 6 12 12 12 11 1 12 esempio

Le bisecie possono esistere anche se non sono visivamente ovvie.
ad es. 1000000 1000001→ falsy:

1000000 1000001 esempio

ad es. 1000000 1000001 1→ verità:

1000000 1000001 1 esempio

(Grazie a nces.ed.gov per la generazione dei grafici a torta.)

Casi test

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

punteggio

Vince il codice più breve in byte. Tiebreaker è la risposta precedente.


30
Credo che intendi la torta settata?
Alex A.

@HelkaHomba, puoi riorganizzare i settori per farlo funzionare, ed è quello che intendevi per "organizzare i numeri in modo diverso può rimuovere le bisettrici"?
Solomon Ucko,

@SolomonUcko Non è possibile riorganizzare i settori.
Calvin's Hobbies,

1
Solo [2 1 3 4] dei casi falsi deve essere effettivamente valutato. Gli altri casi falsi vengono facilmente respinti perché la loro somma è dispari (o la loro lunghezza è <2).
Benny Jobigan,

Risposte:


12

J, 18 byte

5 byte grazie a Dennis.

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

@HelkaHomba : Nope.

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

Versione precedente a 23 byte:

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

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)

Spiegazione

La somma di tutte le sottostringhe è calcolata da black_magic. Il +/\calcolare le somme parziali.

Ad esempio, a b c ddiventa a a+b a+b+c a+b+c+d.

L' -/~poi costruisce una tabella sottrazione base all'ingresso, così x y zdiventa:

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

Se applicato a a a+b a+b+c a+b+c+d, il risultato sarebbe:

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

Questo ha calcolato le somme di tutte le sottostringhe che non contengono a.

Ciò garantisce che sia sufficiente, poiché se una bisection contiene a, l'altra bisection non conterrà ae inoltre non si avvolgerà.


3
Con qualche ristrutturazione, è possibile arrivare a 13 byte:+/e.&,2*+/\\.
Zgarb

10

Gelatina , 9 8 byte

Ḥ+\©_Sf®

Restituisce un elenco non vuoto (verità) o un elenco vuoto (falsa). Provalo online! o verifica tutti i casi di test .

Come funziona

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

Julia, 34 30 29 byte

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

Grazie a @GlenO per giocare a golf a 1 byte!

Provalo online!

Come funziona

Dopo aver memorizzato la somma cumulativa di 2x in x , sottraggiamo il vettore di riga x ' dal vettore di colonna x , producendo la matrice di tutte le possibili differenze. In sostanza, questo calcola le somme di tutti i sottoarrays adiacenti di x che non contengono il primo valore, i loro negativi e gli 0 nella diagonale.

Infine, testiamo se la somma dell'array originale x appartiene alla matrice generata. In tal caso, la somma di almeno una delle liste secondarie adiacenti è uguale alla metà esatta della somma dell'intera lista, il che significa che esiste almeno una bisettrice.


15
Guardiamo mentre Dennis dà 5 risposte prima che qualcun altro ne dia una.
Calvin's Hobbies,

6

Python 2, 64 byte

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

Cerca in modo ricorsivo di rimuovere elementi dalla parte anteriore o finale fino a quando la somma di ciò che rimane è uguale alla somma di ciò che è stato eliminato, che è memorizzato s. Richiede tempo esponenziale nella lunghezza dell'elenco.

Dennis ha salvato 3 byte con pop.


Una strana alternativa che fornisce elenchi: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 byte

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

L'idea è di verificare se esiste un elenco secondario di lcui somma è uguale sum l/2. Generiamo le somme di queste liste secondarie come scanr(:)[]l>>=scanl(+)0. Diamo un'occhiata a come funzional=[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

Vecchi 43 byte:

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

Genera l'elenco cdi somme cumulative. Quindi, controlla se due di queste somme differiscono sum l/2controllando se si tratta di un elemento dell'elenco delle differenze (-)<$>c<*>c.


4

Pyth, 10 9 byte

}sQmysd.:

Provatelo in Pyth compilatore .

Come funziona

       .:  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

In realtà, 21 byte

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

Provalo online!

Questo programma stampa a 0per i casi falsi e un numero intero positivo per i casi veri.

Spiegazione:

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

Versione non competitiva, 10 byte

;Σ@2*σ;)-∩

Provalo online!

Questo programma genera un elenco vuoto per casi falsi e un elenco non vuoto in caso contrario. È essenzialmente un porto della risposta Jelly di Dennis . Non è in competizione perché la somma cumulativa e la funzionalità di differenza vettorializzata dopo la data della sfida.

Spiegazione:

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

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

Grazie a @xnor per giocare a golf con 4 8 byte!

Provalo su Ideone . (esclusi casi di test più grandi)


Ho capito che puoi fare n=sum(x)per fare n in ...; non fa male usare un valore maggiore per n.
xnor

Ooh, è intelligente. Grazie!
Dennis,

3

MATL , 10 byte

EYst!-Gs=z

L'output è il numero di bisettrici.

Provalo online!

Spiegazione

Stesso approccio della risposta Julia di Dennis .

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

Rubino, 60 53 byte

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

Genera tutte le partizioni possibili eseguendo ogni rotazione dell'array di input e quindi prendendo tutte le sezioni di lunghezza 1 .. n, dove si ntrova la dimensione dell'array di input. Quindi controlla se esiste una partizione con una somma la metà della somma totale dell'array di input.


2

JavaScript (ES6), 83 byte

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

Genera tutte le possibili somme, quindi controlla se la metà dell'ultima somma (che è la somma dell'intero elenco) appare nell'elenco. (Generare le somme nell'ordine un po 'scomodo per organizzare la somma che ho bisogno di essere salva per ultimo 4 byte.)


2

Dyalog APL, 12 byte

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

Provalo con TryAPL .

Come funziona

+/∊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 byte

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

Provalo online!

Sono tornato 2,75 anni dopo per battere la mia vecchia soluzione di oltre il 25% usando un nuovo metodo.

Questa versione più lunga di 1 byte è un po 'più chiara.

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

Provalo online!

L'idea è di memorizzare l'insieme di somme cumulative tcome bit di k, impostando bit 2*tper indicare che tè una somma cumulativa. Quindi, controlliamo se due somme cumulative differiscono della metà della somma della lista (finale t) spostando il bit kcosì tanto e facendo bit &a bit con l'originale per vedere il risultato è diverso da zero (verità).


1

APL, 25 caratteri

Supponendo che l'elenco sia fornito X ← 1 2 3 4.

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

Spiegazione:

Prima nota che APL valuta il modulo da destra a sinistra. Poi:

  • X←⎕ accetta l'input dell'utente e lo memorizza X

  • ⍴X dà la lunghezza di X

  • ⍳⍴X i numeri da 1 a ⍴X

  • Gli e in {2×+/⍺↑⍵↓X,X}sono l'argomento sinistro e destro di una funzione diadica che stiamo definendo tra parentesi graffe.

    • Ora per la ⍺↑⍵↓X,Xparte: X,Xconcatena appena X con se stesso; e sono prendere e rilasciare.
    • +/riduce / piega +l'elenco alla sua destra

    Quindi 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è giusto idx ∘.brace idx. ( è la mappa diagonale; ∘.è il prodotto esterno)

    Quindi questo ci dà una ⍴Xdalla ⍴Xmatrice che contiene due volte le somme di tutte le liste parziali collegati.

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

    L'ultima cosa che dobbiamo fare è verificare se la somma di Xè da qualche parte all'interno di questa matrice.

  • Con che facciamo (+/X)∊matrix.


1

C, 161 145 129 byte

  • salvato pochi byte grazie a @LeakyNun
  • salvato pochi byte grazie 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;}

Ungolfed prova 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
}

Forse puoi salvare alcuni byte spostando le dichiarazioni delle variabili al primo livello e cambiando i<n;i++in i++<n(anche se potresti dover gestire alcuni offset.
Leaky Nun

0

Haskell, 68 byte

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

La funzione fcrea innanzitutto un elenco delle somme di tutte le possibili sezioni dell'elenco specificato. Quindi confronta con la somma totale degli elementi dell'elenco. Se arriviamo ad un certo punto a metà della somma totale, allora sappiamo che abbiamo una bisection. Sto anche usando il fatto che se tu takeo droppiù elementi di quelli presenti nell'elenco, Haskell non genera un errore.


0

Mathematica, 48 byte

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

Funzione anonima, simile in azione alle numerose altre risposte.

Outer[Plus, #, -#], quando agisce Accumulate@# (che a sua volta agisce sulla lista di input, fornendo una lista di totali successivi) genera essenzialmente la stessa tabella, come in fondo alla risposta di Leaky Nun.

!FreeQ[..., Last@#/2]controlla se non(Last@#)/2 è assente dalla tabella risultante eLast@# è l'ultimo dei totali successivi, ovvero la somma di tutti gli elementi dell'elenco di input.

Se questa risposta è in qualche modo interessante, non è a causa di un nuovo algoritmo, ma più sui trucchi specifici di Mathematica; es. !FreeQè bello, rispetto a MemberQ, poiché non richiede un appiattimento della tabella che controlla e salva un byte.


Penso che !FreeQ[2Tr/@Subsequences@#,Tr@#]&dovrebbe funzionare, ma non avrò 10.4 disponibili per testarlo per i prossimi 10 giorni circa.
Martin Ender,

@MartinEnder Sembra certamente che funzioni, ma sono al 10.2, quindi è quello che ho
LLlAMnYP,

0

APL (NARS), caratteri 95, byte 190

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

Considera un array di input di 4 elementi: 1 2 3 4. Come possiamo scegliere l'utile per questa partizione di esercizi di quel set? Dopo alcuni pensano che la partizione di questi 4 elementi che possiamo usare siano descritti nel numero binario a sinistra:

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

(1001 o 1011 ecc potrebbero essere in quell'insieme ma già abbiamo 0110 e 0100 ecc) quindi un cappello solo per scrivere una funzione che dal numero di elementi dell'array di input costruisce questi numeri binari ... sarebbe:

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

che dall'ingresso 1 2 4 8 [2 ^ 0..lenBytesArgument-1] trova 3 6 12, 7 14, 15; quindi trova binario di questi numeri e usandoli trova le giuste partizioni dell'array di input ... Ho provato la funzione c solo per quell'input 4 elementi, ma sembra che sia ok per altri numeri di elementi ...

test:

  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 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.