Copertine a somma zero


38

introduzione

Considera un elenco non vuoto L di numeri interi. Una sezione di somma zero di L è una sottosequenza contigua di L la cui somma è uguale a 0. Ad esempio, [1, -3, 2] è una sezione di somma zero di [-2, 4, 1, -3, 2, 2 , -1, -1] , ma [2, 2] non lo è (perché non si somma a 0) e nemmeno [4, -3, -1] (perché non è contiguo).

Una raccolta di sezioni a somma zero di L è una copertura a somma zero di L se ogni elemento appartiene ad almeno una delle sezioni. Per esempio:

L = [-2, 4, 1, -3, 2, 2, -1, -1]
A = [-2, 4, 1, -3]
B =        [1, -3, 2]
C =                  [2, -1, -1]

I tre somma zero affetta A , B e C formano una copertura somma zero L . Più copie della stessa sezione possono apparire in una copertina a somma zero, in questo modo:

L = [2, -1, -1, -1, 2, -1, -1]
A = [2, -1, -1]
B =        [-1, -1, 2]
C =                [2, -1, -1]

Naturalmente, non tutte le liste hanno una copertura a somma zero; alcuni esempi sono [2, -1] (ogni slice ha una somma diversa da zero) e [2, 2, -1, -1, 0, 1] (il 2 più a sinistra non fa parte di una slice a somma zero).

L'obiettivo

Il tuo input è un elenco intero non vuoto L , preso in qualsiasi formato ragionevole. Il risultato deve essere un valore veritiero se L ha una copertura a somma zero e un valore falso in caso contrario.

È possibile scrivere un programma completo o una funzione e vince il conteggio dei byte più basso.

Casi test

[-1] -> False
[2,-1] -> False
[2,2,-1,-1,0,1] -> False
[2,-2,1,2,-2,-2,4] -> False
[3,-5,-2,0,-3,-2,-1,-2,0,-2] -> False
[-2,6,3,-3,-3,-3,1,2,2,-2,-5,1] -> False
[5,-8,2,-1,-7,-4,4,1,-8,2,-1,-3,-3,-3,5,1] -> False
[-8,-8,4,1,3,10,9,-11,4,4,10,-2,-3,4,-10,-3,-5,0,6,9,7,-5,-3,-3] -> False
[10,8,6,-4,-2,-10,1,1,-5,-11,-3,4,11,6,-3,-4,-3,-9,-11,-12,-4,7,-10,-4] -> False
[0] -> True
[4,-2,-2] -> True
[2,2,-3,1,-2,3,1] -> True
[5,-3,-1,-2,1,5,-4] -> True
[2,-1,-1,-1,2,-1,-1] -> True
[-2,4,1,-3,2,2,-1,-1] -> True
[-4,-1,-1,6,3,6,-5,1,-5,-4,5,3] -> True
[-11,8,-2,-6,2,-12,5,3,-7,4,-7,7,12,-1,-1,6,-7,-4,-5,-12,9,5,6,-3] -> True
[4,-9,12,12,-11,-11,9,-4,8,5,-10,-6,2,-9,10,-11,-9,-2,8,4,-11,7,12,-5] -> True

Con "ogni elemento appartiene a una delle sezioni", stai trattando lo stesso valore a diversi indici come distinto?
ngenesi,

@ngenisis Sì, sono distinti e ognuno dovrebbe trovarsi in una sezione che contiene l'indice corrispondente.
Zgarb,

2
Il terzo esempio di falsa non dovrebbe [2,2,-1,-1,0,1] -> Falseessere vero dal momento che entrambe le sezioni [2,-1,-1]e si [-1,0,1]aggiungono a zero e tutti i loro elementi sono nell'elenco originale?
Dfernan,

Il 2 più a sinistra non fa parte di alcuna sezione a somma zero. È un po 'poco chiaro, ma devono trovarsi in una sezione che "contiene il loro indice".
Zgarb,

Inteso. Questo lo rende più difficile. : o)
dfernan,

Risposte:


11

Gelatina , 13 12 byte

JẆịS¥ÐḟċþJḄẠ

Provalo online!

Come funziona

JẆịS¥ÐḟċþJḄẠ  Main link. Argument: A (array)

J             Yield all indices of A.
 Ẇ            Window; yield all slices of indices.
     Ðḟ       Filter; keep slices for which the link to the left returns 0.
    ¥           Combine the two atoms to the left into a dyadic chain.
  ị               Retrieve the elements of A at the slice's indices.
   S              Take the sum.
         J    Yield the indices of A.
       ċþ     Count table; count how many times each index appears in each table.
          Ḅ   Unbinary; convery the array of counts of each index from base 2 to 
              integer. This yields 0 iff an index does not appear in any slice.
           Ạ  All; return 1 iff all integers are non-zero.

9

Mathematica, 66 65 byte

Salvato 1 byte e si spera abbia imparato un nuovo trucco per il futuro, grazie alla ngenisi!

Due alternative ugualmente lunghe, entrambe sono funzioni senza nome che prendono un elenco di numeri interi come input e return Trueo False:

And@@Table[0==Product[Tr@#[[i;;j]],{i,k},{j,k,l}],{k,l=Tr[1^#]}]&

0==Norm@Table[Product[Tr@#[[i;;j]],{i,k},{j,k,l}],{k,l=Tr[1^#]}]&

In entrambi i casi, Tr@#[[i;;j]]calcola la somma della porzione dell'input da posizione ia posizione j(1-indicizzata). Product[...,{i,k},{j,k,l}]moltiplica insieme tutte queste somme di fetta, come iintervalli su indici al massimo ke jintervalli su indici almeno k. (Si noti che l=Tr[1^#]definisce lla somma di 1tutti i poteri nell'elenco di input, che è semplicemente la lunghezza dell'elenco.) In altre parole, questo prodotto è uguale a 0 se e solo se l' kelemento th appartiene a una sezione di somma zero .

Nella prima versione, ciascuno di questi prodotti viene confrontato 0e And@@restituisce Trueesattamente quando ogni singolo prodotto è uguale 0. Nella seconda versione, l'elenco dei prodotti è influenzato dalla funzione Norm(la lunghezza del lvettore tridimensionale), che equivale a 0se e solo se ogni voce è uguale 0.


1
Tr[1^#]salva 1byte da Length@#.
ngenesi,

Funzionerebbe 0^invece di 0==? Non sono sicuro di come Mathematica lo gestisca. (ritorneresti 1/ 0invece di true/ false)
Cyoce,

1
Bella idea, ma Mathematica torna Indeterminateper 0^0. Inoltre, 1/ 0non sono in realtà verità / falsità in Mathematica — è troppo fortemente tipizzato per rendere felici i golfisti :)
Greg Martin

7

Mathematica, 65 64 byte

Grazie a ngenisis per il salvataggio di 1 byte.

Union@@Cases[Subsequences[x=Range@Tr[1^#]],a_/;Tr@#[[a]]==0]==x&

Preferirei trovare una soluzione di abbinamento del modello puro, ma si sta rivelando complicato (e cose come {___,a__,___}sono sempre super lunghe).


4

Haskell, 94 byte

import Data.Lists
g x=(1<$x)==(1<$nub(id=<<[i|(i,0)<-fmap sum.unzip<$>powerslice(zip[1..]x)]))

Esempio di utilizzo: g [-11,8,-2,-6,2,-12,5,3,-7,4,-7,7,12,-1,-1,6,-7,-4,-5,-12,9,5,6,-3] -> True.

Come funziona (usiamo [-1,1,5,-5]per l'input):

        zip[1..]x  -- zip each element with its index
                   -- -> [(1,-1),(2,1),(3,5),(4,-5)]
      powerslice   -- make a list of all continuous subsequences
                   -- -> [[],[(1,-1)],[(1,-1),(2,1)],[(1,-1),(2,1),(3,5)],[(1,-1),(2,1),(3,5),(4,-5)],[(2,1)],[(2,1),(3,5)],[(2,1),(3,5),(4,-5)],[(3,5)],[(3,5),(4,-5)],[(4,-5)]]
    <$>            -- for each subsequence
   unzip           --   turn the list of pairs into a pair of lists
                   --   -> [([],[]),([1],[-1]),([1,2],[-1,1]),([1,2,3],[-1,1,5]),([1,2,3,4],[-1,1,5,-5]),([2],[1]),([2,3],[1,5]),([2,3,4],[1,5,-5]),([3],[5]),([3,4],[5,-5]),([4],[-5])]
  fmap sum         --   and sum the second element
                   --   -> [([],0),([1],-1),([1,2],0),([1,2,3],5),([1,2,3,4],0),([2],1),([2,3],6),([2,3,4],1),([3],5),([3,4],0),([4],-5)]
 [i|(i,0)<-    ]   -- take all list of indices where the corresponding sum == 0
                   -- -> [[],[1,2],[1,2,3,4],[3,4]]
 id=<<             -- flatten the list
                   -- -> [1,2,1,2,3,4,3,4]
nub                -- remove duplicates
                   -- -> [1,2,3,4]

(1<$x)==(1<$    )  -- check if the above list has the same length as the input list. 

powersliceè un nome così fantastico.
Zgarb,

3

Rubino, 81 byte

Provalo online

Soluzione semplicistica di forza bruta; per ogni elemento dell'array, prova a trovare una sezione a somma zero che lo contenga.

->a{(0..l=a.size).all?{|i|(0..i).any?{|j|(i..l).any?{|k|a[j..k].inject(:+)==0}}}}

3

J, 36 35 byte

#\*/@e.[:;]({:*0=[:+/{.)@|:\.\@,.#\

Per ogni subsum aggiungo gli indici dell'elemento e mantengo gli indici se subsum è 0e quindi controllo se ogni indice è presente.

Trucco: è possibile generare indici basati su 1 di un elenco con la #\lunghezza di ogni prefisso.

Uso:

   (#\*/@e.[:;]({:*0=[:+/{.)@|:\.\@,.#\) 2 _1 _1 2
1
   (#\*/@e.[:;]({:*0=[:+/{.)@|:\.\@,.#\) 2 _1
0

Provalo online qui.


Penso che puoi salvare 2 byte usando il trucco di base 1 per la somma e usando un appiattimento composto#\*/@e.&,]({:*0=1#.{.)@|:\.\@,.#\
miglia

2

JavaScript (ES6), 109 byte

f=([q,...a],b=[],c=[])=>1/q?f(a,[...b,0].map((x,i)=>x+q||(c=c.map((n,j)=>n|i<=j)),c.push(0)),c):c.every(x=>x)

Test snippet


1

Python, 123 120 byte

-3 byte grazie a @Zgarb

Popola un elenco con le stesse dimensioni dell'input con sezioni a somma zero e sovrascrive in base agli indici, restituendo alla fine la sua uguaglianza all'originale.

def f(l):
 s=len(l);n=[0]*s
 for i in range(s):
  for j in range(i,s+1):
   if sum(l[i:j])==0:n[i:j]=l[i:j]
 return n==l

1
Penso che puoi usare 0come segnaposto anziché None. Non ci saranno falsi positivi, perché ogni 0input è sempre parte o una porzione a somma zero.
Zgarb,

Hai ragione. Ci ho pensato, ma ho finito per concludere che potrebbe incorrere in falsi positivi.
Dfernan,

0

Scala, 49 byte

% =>(1 to%.size)flatMap(%sliding)exists(_.sum==0)

Provalo su ideone

Uso:

val f:(Seq[Int]=>Boolean)= % =>(1 to%.size)flatMap(%sliding)exists(_.sum==0)
f(Seq(4, -2, -2)) //returns true

Ungolfed:

array=>(1 to array.size)
  .flatMap(n => array.sliding(n))
  .exists(slice => slice.sum == 0)

Spiegazione:

% =>            //define a anonymouns function with a parameter called %
  (1 to %.size) //create a range from 1 to the size of %
  flatMap(      //flatMap each number n of the range
    %sliding    //to an iterator with all slices of % with length n
  )exists(      //check whether there's an iterator with a sum of 0
    _.sum==0
  )

Non sono esattamente sicuro di come funzioni, ma penso che dovrebbe fallire in alcuni dei casi di test veritieri.
Zgarb,

@Zgarb Ho aggiunto un link a ideone, in modo da poter verificare che sia corretto. Fondamentalmente è una forza bruta, provando ogni possibile fetta.
corvus_192,

Puoi usare %come nome parametro? Freddo!
Cyoce,

@Cyoce Puoi usare praticamente qualsiasi carattere Unicode tranne .,;:()[]{}\"'. Abbastanza utile per giocare a golf, perché vengono separati dalle lettere dall'analisi, quindi puoi risparmiare un po 'di spazio.
corvus_192,

Ho controllato i casi di test e sembra dare trueil secondo caso di falsa.
Zgarb,

0

Python, 86 byte

def f(l):
 r=range(len(l))
 if[i for i in r for j in r if sum(l[j:j+i+1])==0]:return 1

Verità = 1 Falso = Nessuno


Ciò restituisce erroneamente 1per il terzo caso di test.
Zgarb,

1
In realtà restituisce 1per tutti i casi di test tranne i primi due falsi.
Dfernan,

0

Clojure, 109 byte

#(=(count %)(count(set(flatten(for[r[(range(count %))]l r p(partition l 1 r):when(=(apply +(map % p))0)]p))))

Genera tutte le partizioni che si sommano a zero, verifica che abbia indici distinti "lunghezza del vettore di input".


0

PHP, 104 byte

Forza bruta e ancora oltre 99 byte. :-(

for($p=$r=$c=$argc;$s=--$p;)for($i=$c;$s&&$k=--$i;)for($s=0;$k<$c&&($r-=!$s+=$argv[$k++])&&$s;);echo!$r;

prende input dagli argomenti della riga di comando, 1per la verità, vuoto per la falsa. Corri con -r.

abbattersi

for($p=$r=$argc;$s=$p--;)   # loop $p from $argc-1 to 0 with dummy value >0 for $s
    for($i=$p;$s&&$k=$i--;)     # loop $i (slice start) from $p to 1, break if sum is 0
        for($s=0;                   # init sum to 0
            $k<$argc                # loop $k (slice end) from $i to $argc-1
            &&($r-=!$s+=$argv[$k++])    # update sum, decrement $r if sum is 0
            &&$s;);                     # break loop if sum is 0
echo!$r;                    # $r = number of elements that are not part of a zero-sum slice

$argv[0]contiene il nome file; se eseguito con -r, sarà -e valuterà le 0operazioni numeriche.


0

JavaScript (ES6), 102 byte

a=>(g=f=>a.map((_,i)=>f(i)))(i=>g(j=>j<i||(t+=a[j])||g(k=>b[k]&=k<i|k>j),t=0),b=g(_=>1))&&!/1/.test(b)

Calcola le somme parziali per tutti gli elementi i..jinclusi e reimposta gli elementi rilevanti di bda 1a 0quando trova una somma zero, verificando infine che non siano 1rimasti.

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.