Chcę zwrócić True
wtedy i tylko wtedy, gdy 3 z 4 wartości logicznych są prawdziwe.
Najbliższe otrzymałem to (x ^ y) ^ (a ^ b)
:
Co powinienem zrobić?
boolean-logic
Simon Kuang
źródło
źródło
not a ^ not b ^ not c ^ not d
jest prawdziwy, gdy dokładnie jedna z zanegowanych wartości jest prawdziwa. Oznacza to, że z oryginalnych wartości dokładnie jeden był fałszywy.(!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d)
.Odpowiedzi:
Proponuję napisać kod w sposób, który wskazuje, co masz na myśli. Jeśli chcesz, aby 3 wartości były prawdziwe, wydaje mi się naturalne, że wartość 3 gdzieś się pojawia.
Na przykład w
C++
:Jest to dobrze zdefiniowane w
C++
:standard (§4.7/4)
oznacza, że konwersjabool
naint
daje oczekiwane wartości 0 lub 1.W Javie i C # możesz użyć następującej konstrukcji:
źródło
if (!!a + !!b + !!c + !!d == 3)
łatwiej jest pisać, chociaż nie wiem, czy kompilatory optymalizują to, czy nie# 1: Używanie rozgałęzienia?: 3 lub 4 operacje
# 2 Bez rozgałęzienia, 7 operacji
Kiedy już używałem profilowania wszystkiego, odkryłem, że rozwiązania nierozgałęziające były znacznie szybsze w działaniu, ponieważ procesor mógł lepiej przewidywać ścieżkę kodu i wykonywać więcej operacji w tandemie. Jednak w instrukcji rozgałęzienia jest około 50% mniej pracy.
źródło
Gdyby to był Python, napisałbym
Lub
Lub
Lub
Lub
Lub
Lub
Wszystko to działa, ponieważ wartości logiczne są podklasami liczb całkowitych w Pythonie.
Lub zainspirowany tą zgrabną sztuczką ,
źródło
a=5;not not a == 1
. Wadą jest brak prawdziwego typu boolowskiego.bool
:)Długa, ale bardzo prosta (rozłączna) postać normalna:
Można to uprościć, ale wymaga to więcej przemyślenia: P
źródło
(a & b & (c ^ d)) | ((a ^ b) & c & d)
?Nie wiem, czy to prostsze, ale może.
((x xor y) and (a and b)) or ((x and y) and (a xor b))
źródło
Jeśli chcesz użyć tej logiki w języku programowania, moja sugestia jest taka
Lub jeśli chcesz, możesz umieścić je wszystkie w jednym wierszu:
Możesz również uogólnić ten problem, aby
n of m
:źródło
Ta odpowiedź zależy od systemu reprezentacji, ale jeśli 0 jest jedyną wartością interpretowaną jako fałsz i
not(false)
zawsze zwraca tę samą wartość liczbową, tonot(a) + not(b) + not(c) + not(d) = not(0)
powinno załatwić sprawę.źródło
Mając na uwadze, że SO w przypadku pytań programistycznych, a nie tylko problemów logicznych, odpowiedź oczywiście zależy od wyboru języka programowania. Niektóre języki obsługują funkcje, które są rzadkie w innych.
Na przykład w C ++ możesz przetestować swoje warunki za pomocą:
Powinien to być najszybszy sposób sprawdzenia w językach, które obsługują automatyczną (niskiego poziomu) konwersję z typów logicznych na całkowite. Ale znowu nie ma ogólnej odpowiedzi na ten problem.
źródło
Najlepsze, co mogę zrobić, to
((x ^ y) ^ (a ^ b)) && ((a || x) && (b || y))
źródło
Pierwsze wyrażenie wyszukuje 1 lub 3
true
z 4. Drugi eliminuje 0 lub 1 (a czasem 2)true
z 4.źródło
Java 8, odfiltruj wartości fałszywe i policz pozostałe wartości prawdziwe:
Następnie możesz go użyć w następujący sposób:
Łatwo uogólnia do sprawdzania
n
zm
przedmiotów jest prawdziwe.źródło
Aby sprawdzić, czy przynajmniej
n
ze wszystkichBoolean
są prawdziwe (n musi być mniejsze lub równe całkowitej liczbieBoolean
: p)Edycja : po komentarzu @ Cruncher
Aby sprawdzić 3
boolean
z 4Inny :
((c & d) & (a ^ b)) | ((a & b) & (c ^ d))
( Szczegóły )źródło
Oto sposób, w jaki możesz to rozwiązać w C # za pomocą LINQ:
źródło
To jest symetryczna funkcja boolowska
S₃(4)
. Symetryczna funkcja boolowska jest funkcją boolowską, która zależy tylko od ilości ustawionych wejść, ale nie zależy od tego, które z nich są. Knuth wspomina o funkcjach tego typu w sekcji 7.1.2 w tomie 4 książki The Art of Computer Programming.S₃(4)
można obliczyć za pomocą 7 operacji w następujący sposób:Knuth pokazuje, że jest to optymalne, co oznacza, że nie można tego zrobić w mniej niż 7 operacjach przy użyciu zwykłych operatorów:
&&, || , ^, <,
i>
.Jeśli jednak chcesz użyć tego w języku, w którym używa się
1
prawdy i0
fałszu, możesz również łatwo użyć dodawania:co sprawia, że twój zamiar jest całkiem jasny.
źródło
Z czysto logicznego punktu widzenia to właśnie wymyśliłem.
Zgodnie z zasadą gołębnika, jeśli dokładnie 3 jest prawdziwe, to albo aib jest prawdą, albo cid jest prawdą. Wtedy wystarczy połączyć każdy z tych przypadków z dokładnie jednym z pozostałych 2.
Tabela prawdy Wolframa
źródło
mine <=> his
nie wiem, co powiedzieć, ponieważ można by się tego spodziewać.Jeśli używasz narzędzia do wizualizacji logiki, takiego jak Mapy Karnaugha, zobaczysz, że jest to problem, w którym nie możesz uniknąć pełnego wyrażenia logicznego, jeśli chcesz go zapisać w jednym wierszu if (...). Lopina już to pokazała, prościej się nie da napisać. Możesz trochę pomyśleć, ale będzie to trudne do odczytania dla Ciebie ORAZ dla maszyny.
Rozwiązania liczenia nie są złe i pokazują, czego naprawdę szukasz. Skuteczne liczenie zależy od języka programowania. Rozwiązania tablicowe w Pythonie lub LinQ są przyjemne dla oka, ale uwaga, to jest WOLNE. Wolf's (a + b + x + y) == 3 będzie działać dobrze i szybko, ale tylko wtedy, gdy twój język zrównuje „prawda” z 1. Jeśli „prawda” jest reprezentowana przez -1, będziesz musiał przetestować na -3: )
Jeśli twój język używa prawdziwych wartości logicznych, możesz spróbować zaprogramować go jawnie (ja używam! = Jako testu XOR):
„x! = y” działa tylko wtedy, gdy x, y są typu boolowskiego. Jeśli są innego typu, w których 0 jest fałszywe, a wszystko inne jest prawdą, może się to nie powieść. Następnie użyj logicznego XOR, lub ((bool) x! = (Bool) y), lub napisz „if (x) return (y == false) else return (y == true);”, co jest trochę więcej pracować na komputerze.
Jeśli Twój język programowania udostępnia operator trójskładnikowy?:, Możesz go skrócić do
który zachowuje trochę czytelności, lub agresywnie skraca
Ten kod wykonuje dokładnie trzy testy logiczne (stan a, stan b, porównanie x i y) i powinien być szybszy niż większość innych odpowiedzi tutaj. Ale musisz to skomentować, inaczej nie zrozumiesz po 3 miesiącach :)
źródło
Jest tu wiele dobrych odpowiedzi; oto alternatywna formuła, której nikt inny jeszcze nie opublikował:
źródło
Podobna do pierwszej odpowiedzi, ale czysta Java:
Wolę liczyć je jako liczby całkowite, ponieważ dzięki temu kod jest bardziej czytelny.
źródło
W Pythonie , aby zobaczyć, ile iterowalnych elementów jest True, użyj
sum
(jest to dość proste):Ustawiać
Rzeczywisty test
Wynik
źródło
Jeśli szukasz rozwiązania na papierze (nie programistycznego), to mapy K i algorytmy Quine-McCluskey są tym, czego szukasz, pomagają ci zminimalizować funkcję boolowską.
W twoim przypadku wynik jest
Jeśli chcesz to zrobić programowo, z niestałą ilością zmiennych i niestandardowym „progiem”, po prostu iterowanie przez listę wartości logicznych i liczenie wystąpień „prawda” jest całkiem proste i proste.
źródło
Biorąc pod uwagę 4 wartości logiczne, a, b, x, y, zadanie to przekłada się na następującą instrukcję C:
źródło
true
równa się 1. To nie jest prawda (gra słów nie zamierzona) we wszystkich językach / przypadkach. blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspxjest tym, czego chcesz. Zasadniczo wziąłem twój kod i dodałem sprawdzanie, czy w rzeczywistości 3 są prawdziwe, a nie 3 są fałszywe.
źródło
Pytanie programistyczne bez odpowiedzi z rekurencją? Niepojęty!
Jest wystarczająco dużo odpowiedzi „dokładnie 3 z 4 prawd”, ale tutaj jest uogólniona wersja (w języku Java) wyrażenia „dokładnie m z n praw” (w przeciwnym razie rekursja nie jest tego warta) tylko dlatego, że można:
Można to nazwać czymś takim:
który powinien zwrócić
true
(ponieważ 5 z 8 wartości było prawdą, zgodnie z oczekiwaniami). Niezupełnie zadowolony ze słów „prawda” i „fałsz”, ale nie mogę teraz wymyślić lepszej nazwy… Zwróć uwagę, że rekursja kończy się, gdy znaleziono zbyt wieletrue
lub zbyt wielefalse
wartości.źródło
true
. Może coś takiegocontainsNumberOfTrueValues()
. Tak na marginesie: nazewnictwo Smalltalk byłby znacznie bardziej nadaje się do tego, iż:doesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar
. Prawdopodobnie za długo jak na gust niektórych deweloperów Javy, ale Smalltalkers nigdy nie boją się odpowiedniego nazewnictwa ;-)containsTruth
dosłownie oznacza „zawiera pewną nieujawnioną ilość prawdy”, więc uważam, że jest w porządku.Ponieważ czytelność jest dużym problemem, możesz użyć opisowego wywołania funkcji (zawijając dowolną z sugerowanych implementacji). Jeśli to obliczenie trzeba wykonać w wielu miejscach, wywołanie funkcji jest najlepszym sposobem na ponowne użycie i wyjaśnia dokładnie, co robisz.
źródło
W PHP, czyniąc go bardziej dynamicznym (na wypadek gdybyś zmienił liczbę warunków itp.):
źródło
Chociaż mógłbym pokazać, że jest to dobre rozwiązanie, odpowiedź Sama Hocevara jest łatwa zarówno do napisania, jak i do zrozumienia później. W mojej książce to sprawia, że jest lepiej.
źródło
Oto kod C #, który właśnie napisałem, ponieważ mnie zainspirowałeś:
Wymaga dowolnej liczby argumentów i powie Ci, czy n z nich jest prawdą.
i tak to nazywasz:
Możesz więc teraz przetestować 7/9 lub 15/100, jak chcesz.
źródło