Pokrycia zerowej sumy

38

Wprowadzenie

Rozważ niepustą listę L liczb całkowitych. Plaster o sumie zerowej z L oznacza ciągłą podciągiem L których suma wynosi 0. Na przykład, [1, -3, 2] jest plaster o sumie zerowej [-2, 4, 1, -3, 2, 2 , -1, -1] , ale [2, 2] nie jest (ponieważ nie sumuje się do 0), podobnie jak [4, -3, -1] (ponieważ nie jest ciągły).

Zbiór plastry o sumie zerowej L jest pokrywa sumie zerowej z L , jeśli każdy element należący do co najmniej jednego segmentu. Na przykład:

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

Trzy wycinki A , B i C sumy zerowej tworzą pokrycie L dla sumy zerowej . Wiele kopii tego samego wycinka może pojawić się w okładce o sumie zerowej, tak jak to:

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

Oczywiście nie wszystkie listy mają zerową sumę; niektóre przykłady to [2, -1] (każdy wycinek ma niezerową sumę) i [2, 2, -1, -1, 0, 1] (skrajne lewe 2 nie jest częścią wycinka o sumie zerowej).

Zadanie

Twoje dane wejściowe to niepusta liczba całkowita L , wykonana w dowolnym rozsądnym formacie. Twój wynik powinien być zgodny z prawdą, jeśli L ma pokrycie sumą zerową, a wartością fałszowania, jeśli nie.

Możesz napisać pełny program lub funkcję, a wygrywa najniższa liczba bajtów.

Przypadki testowe

[-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
Zgarb
źródło
Przez „każdy element należy do jednego z plasterków”, czy traktujesz tę samą wartość przy różnych indeksach jako odrębne?
ngenisis,
@ngenisis Tak, są różne i każdy powinien występować w plastrze zawierającym odpowiedni indeks.
Zgarb,
2
Czy trzeci fałszywy przykład [2,2,-1,-1,0,1] -> Falsenie powinien być prawdziwy, ponieważ oba wycinki [2,-1,-1]i wartość [-1,0,1]dodana do zera oraz wszystkie ich elementy znajdują się na oryginalnej liście?
dfernan
Najbardziej na lewo 2 nie jest częścią żadnego wycinka o sumie zerowej. Jest to trochę niejasne, ale muszą wystąpić w wycinku, który „zawiera ich indeks”.
Zgarb,
Zrozumiany. To sprawia, że ​​jest trudniej. : o)
dfernan

Odpowiedzi:

11

Galaretka , 13 12 bajtów

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

Wypróbuj online!

Jak to działa

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.
Dennis
źródło
9

Mathematica, 66 65 bajtów

Zaoszczędziłem 1 bajt i mam nadzieję, że dzięki ngenisis nauczyłem się nowej sztuczki na przyszłość!

Dwie równie długie alternatywy, z których obie są nienazwanymi funkcjami przyjmującymi listę liczb całkowitych jako dane wejściowe i zwracające Truelub 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^#]}]&

W obu przypadkach Tr@#[[i;;j]]oblicza sumę wycinka danych wejściowych z pozycji ido pozycji j(indeksowane 1). Product[...,{i,k},{j,k,l}]mnoży razem wszystkie te sumy przekrojów, jako iprzedziały powyżej co najwyżej indeksów ki jprzedziały powyżej co najmniej indeksów k. (Zauważ, że l=Tr[1^#]definiuje lsię jako sumę 1wszystkich mocy na liście wejściowej, która jest po prostu długością listy.) Innymi słowy, ten produkt jest równy 0 wtedy i tylko wtedy, gdy kelement th należy do wycinka o sumie zerowej .

W pierwszej wersji każdy z tych produktów jest porównywany 0i And@@zwraca Truedokładnie, gdy każdy pojedynczy produkt jest równy 0. W drugiej wersji na listę produktów działa funkcja Norm(długość lwektora -wymiarowego), która jest równa 0wtedy i tylko wtedy, gdy każdy wpis jest równy 0.

Greg Martin
źródło
1
Tr[1^#]oszczędza 1bajt z Length@#.
ngenisis,
Czy 0^działałby zamiast 0==? Nie jestem pewien, jak Mathematica sobie z tym radzi. (wróciłbyś 1/ 0zamiast true/ false)
Cyoce,
1
Fajny pomysł, ale Mathematica powraca Indeterminatedo 0^0. Poza tym, 1/ w 0rzeczywistości nie są w prawdzie / fałszem w Mathematica - jest zbyt mocno wpisany, aby uszczęśliwić golfistów :)
Greg Martin
7

Mathematica, 65 64 bajtów

Dzięki ngenisis za oszczędność 1 bajtu.

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

Wolę znaleźć rozwiązanie pasujące do czystego wzorca, ale okazuje się być trudne (i rzeczy takie {___,a__,___}są zawsze bardzo długie).

Martin Ender
źródło
4

Haskell, 94 bajty

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

Przykład użycia: 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.

Jak to działa (użyjmy [-1,1,5,-5]do wprowadzania danych):

        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. 
nimi
źródło
powerslicejest tak świetną nazwą funkcji.
Zgarb
3

Ruby, 81 bajtów

Wypróbuj online

Uproszczone rozwiązanie brutalnej siły; dla każdego elementu tablicy spróbuj znaleźć plasterek o sumie zerowej, który go zawiera.

->a{(0..l=a.size).all?{|i|(0..i).any?{|j|(i..l).any?{|k|a[j..k].inject(:+)==0}}}}
Wartość tuszu
źródło
3

J, 36 35 bajtów

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

Do każdego podsumu dodaję indeksy elementu i przechowuję indeksy, jeśli subum jest, 0a następnie sprawdzam, czy każdy indeks jest obecny.

Sztuczka: indeksy listy 1 mogą być generowane z #\np. Długością każdego prefiksu.

Stosowanie:

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

Wypróbuj online tutaj.

randomra
źródło
Myślę, że możesz zaoszczędzić 2 bajty za pomocą sztuczki bazowej 1 do zsumowania i używając skomponowanego spłaszczenia#\*/@e.&,]({:*0=1#.{.)@|:\.\@,.#\
mile
2

JavaScript (ES6), 109 bajtów

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)

Testowy fragment kodu

ETHprodukcje
źródło
1

Python, 123 120 bajtów

-3 bajty dzięki @Zgarb

Wypełnia listę o tym samym rozmiarze co dane wejściowe plasterkami o sumie zerowej i zastępuje zgodnie z indeksami, zwracając jej równość do oryginału na końcu.

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
dfernan
źródło
1
Myślę, że możesz użyć 0jako symbolu zastępczego zamiast None. Nie będzie fałszywych trafień, ponieważ każdy 0z danych wejściowych zawsze zawiera część lub wycinek o sumie zerowej.
Zgarb
Masz rację. Myślałem o tym, ale doszedłem do wniosku, że może to prowadzić do fałszywych trafień.
dfernan
0

Scala, 49 bajtów

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

Wypróbuj w ideone

Stosowanie:

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

Nie golfowany:

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

Wyjaśnienie:

% =>            //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
  )
corvus_192
źródło
Nie jestem do końca pewien, jak to działa, ale myślę, że powinno to zawieść w niektórych z prawdziwych przypadków testowych.
Zgarb,
@Zgarb Dodałem link do ideone, abyś mógł sprawdzić, czy jest poprawny. To w zasadzie brutalna siła, próbująca każdego możliwego kawałka.
corvus_192
Możesz użyć %jako nazwy parametru? Fajne!
Cyoce,
@Cyoce Możesz używać praktycznie dowolnego znaku Unicode, z wyjątkiem .,;:()[]{}\"'. Bardzo przydatne do gry w golfa, ponieważ są one oddzielane od liter przez parsowanie, dzięki czemu można zaoszczędzić trochę białych znaków.
corvus_192
Sprawdziłem przypadki testowe i wydaje się, że dają trueto drugie przypadek fałszowania.
Zgarb,
0

Python, 86 bajtów

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

Prawda = 1 Falsy = Brak

sonrad10
źródło
To niepoprawnie zwraca 1trzeci przypadek testowy.
Zgarb
1
W rzeczywistości zwraca 1wszystkie przypadki testowe, z wyjątkiem dwóch pierwszych przypadków fałszowania.
dfernan
0

Clojure, 109 bajtów

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

Generuje wszystkie partycje, które sumują się do zera, sprawdza, czy ma odrębne indeksy „długości wektora wejściowego”.

NikoNyrh
źródło
0

PHP, 104 bajty

Brutalna siła i wciąż ponad 99 bajtów. :-(

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;

pobiera dane wejściowe z argumentów wiersza poleceń, 1dla prawdy, puste dla fałszu. Uruchom z -r.

awaria

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]zawiera nazwę pliku; jeśli zostanie uruchomiony z -r, będzie to -i oceniać 0dla operacji numerycznych.

Tytus
źródło
0

JavaScript (ES6), 102 bajty

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)

Oblicza sumy częściowe dla wszystkich elementów i..jwłącznie i resetuje odpowiednie elementy bod 1do, 0kiedy znajdzie sumę zerową, ostatecznie sprawdzając, czy nie ma już żadnych 1s.

Neil
źródło