4 / 3'ün Doğru olduğunu test etmek için mantık


163

TrueSadece 4 boolean değerden 3'ü doğruysa geri dönmek istiyorum .

Aldığım en yakın şey (x ^ y) ^ (a ^ b):

Ne yapmalıyım?


10
Hmm, matematiksel formül olmadan düşünebilmemin tek yolu sayımı kullanmak. İyi soru! :)
Ben

10
Fikriniz kötü değil, ama olumsuzlukları almalısınız: not a ^ not b ^ not c ^ not dolumsuzlanan değerlerden biri doğru olduğunda doğrudur. Bu, orijinal değerlerden tam olarak birinin yanlış olduğu anlamına gelir.
Ingo

23
Bu detayların ardındaki asıl probleminiz nedir ?
Kurt

5
@ ^ Değil b ^ değil c ^ değil d yalnızca bir tanesi yanlış VE 3 ise yanlış.
NameSpace

9
Sayısız çözüm açıktır (!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d).
Jason C

Yanıtlar:


248

Kodu ne demek istediğinizi belirtecek şekilde yazmanızı öneririm. 3 değerin doğru olmasını istiyorsanız, 3 değerinin bir yerde göründüğü doğal görünüyor.

Örneğin C++:

if ((int)a + (int)b + (int)c + (int)d == 3)
    ...

Bu da tanımlanır C++: standard (§4.7/4)dönüştürme belirtir booliçinint beklenen değerler, 0 ya da 1 verir.

Java ve C # 'da, aşağıdaki yapıyı kullanabilirsiniz:

if ((a?1:0) + (b?1:0) + (c?1:0) + (d?1:0) == 3)
    ...

23
Bu iyi bir cevap. Bu X / Y olayına benziyor. "X'i Y kullanarak yapmak istiyor, ama Y'yi nasıl yapacağını bilmiyor. X'e sormak yerine Y'ye soruyor." Bir mantık devresi veya bunun gibi bir şey tasarlamadığı sürece (ve sonra yanlış yerde olacaktır), bunu yapmanın en iyi yolu okunabilir bir şekildedir .
NothingsImpossible

2
@NothingsImpossible Soru hakkında XY hiçbir şey yok. Bu, programlamada oldukça yaygın bir sorunun çözümü hakkında açık ve anlaşılır bir sorudur. Y önemsizdir.
Ярослав Рахматуллин

Teşekkürler! Bu gerçekten yapmak istediğim şeydi , ama benim fikrim o kadar beceriksizdi ki, mantıksal mantık için ulaştım.
Simon Kuang

3
if (!!a + !!b + !!c + !!d == 3)Derleyicilerin bunu optimize edip etmediğini bilmememe rağmen yazmak daha kolay
phuclv

2
C ++ 'da bool dan int için döküm gerekli değildir.
PlazmaHH

90

# 1: Dallanma kullanımı?: 3 veya 4 işlem

A ^ B ? C & D : ( C ^ D ) & A

# 2 Dallanmayan, 7 işlem

(A ^ B ^ C ^ D) & ((A & B) | (C & D))

Her şeyi profillemek için kullandığımda, CPU kod yolunu daha iyi tahmin edebildiğinden ve daha fazla işlemi birlikte çalıştırabildiğinden, dallanmayan çözümlerin işlem için biraz daha hızlı çalıştığını gördüm . Yine de buradaki dallanma ifadesinde yaklaşık% 50 daha az çalışma var.


18
+1 - diğer cevaplar çoğu programlama dili için daha iyi olsa da, # 2'niz saf boole mantığındaki en iyi cevaptır.
Brilliand


68

Eğer bu Python olsaydı,

if [a, b, c, d].count(True) == 3:

Veya

if [a, b, c, d].count(False) == 1:

Veya

if [a, b, c, d].count(False) == True:
# In Python True == 1 and False == 0

Veya

print [a, b, c, d].count(0) == 1

Veya

print [a, b, c, d].count(1) == 3

Veya

if a + b + c + d == 3:

Veya

if sum([a, b, c, d]) == 3:

Tüm bu işler, Boolean'lar Python'da tamsayıların alt sınıfları olduğundan.

if len(filter(bool, [a, b, c, d])) == 3:

Veya bu temiz numaradan esinlenerek ,

data = iter([a, b, c, d])
if not all(data) and all(data):

17
+1 Bu, sorunu Python'a doğru bir şekilde çevirerek çözer.
Kurt

Bu biraz tehlikelidir, çünkü insanlar piton bağlamında bir boole bağlamında sıfır olmayan herhangi bir tamsayıyı döndürebilir. Eski C hüner de piton çalışmaktadır: a=5;not not a == 1. Gerçek bir boole tipine sahip olmamanın dezavantajı.
Voo

@Voo Ayrıca var bool:)
thefourtheye

@thefourtheye Ah evet doğru, çift olumsuzluk hile / kesmek çok daha güzel.
Voo

1
Ya da ... ya da .... ya da .... Bir tane olmalı ve tercihen sadece bir tane olmalı. : - / :-)
rz.

53

Uzun ama çok basit, (saygısız) normal form:

 (~a & b & c & d) | (a & ~b & c & d) | (a & b & ~c & d) | (a & b & c & ~d)

Basitleştirilmiş olabilir ama bu daha fazla düşünmeyi gerektirir: P


2
@Ben, bunun zaten içinde bulunduğu çeşitli normal formları verir (DNF).
Mart'ta Riking

8
Nasıl (a & b & (c ^ d)) | ((a ^ b) & c & d)?
user253751

2
Evet, @immibis, Wolfram Alpha'ya göre DNF yazdığım formüldür, bu yüzden aynı boole işlevidir.
Gastón Bengolea

2
Çünkü kodu okuyan biri diğer cevaplardan daha çabuk denenmekte olan şeyi anlayacağını düşünüyorum.
Boluc Papuccuoglu


22

Bu mantığı bir programlama dilinde kullanmak istiyorsanız, önerim

bool test(bool a, bool b, bool c, bool d){
    int n1 = a ? 1 : 0;
    int n2 = b ? 1 : 0;
    int n3 = c ? 1 : 0;
    int n4 = d ? 1 : 0;

    return n1 + n2 + n3 + n4 == 3;
}

İsterseniz, bunların tümünü tek bir satıra koyabilirsiniz:

return (a ? 1 : 0) + (b ? 1 : 0) + (C ? 1 : 0) + (d ? 1 : 0) == 3;

Ayrıca bu sorunu şu şekilde genelleştirebilirsiniz n of m :

bool test(bool *values, int n, int m){
    int sum = 0;
    for(int i = 0; i < m; i += 1){
        sum += values[i] ? 1 : 0;
    }
    return sum == n;
}

12
Beni döv. Okunabilirlik her seferinde akıllılığı yitirir. +1
MikeTheLiar

20

Bu cevap temsil sistemine bağlıdır, ancak 0 yanlış olarak yorumlanan tek değerse ve not(false)her zaman aynı sayısal değeri döndürüyorsa not(a) + not(b) + not(c) + not(d) = not(0), hile yapmalıdır.


18

SO'nun mantıklı problemlerden ziyade programlama soruları için olduğu takdirde, cevabın açıkça bir programlama dili seçimine bağlı olduğunu unutmayın. Bazı diller diğerlerine özgü olmayan özellikleri destekler.

Örneğin, C ++ ile koşullarınızı aşağıdakilerle test edebilirsiniz:

(a + b + c + d) == 3

Bu, boole'den tamsayı türlerine otomatik (düşük düzeyli) dönüştürmeyi destekleyen dillerde check-in yapmanın en hızlı yolu olmalıdır. Fakat yine de, bu sorunun genel bir cevabı yoktur.


2
Göndereceğim cevap bu. Eklenecek bir şey olsa da, kullanılan programlama diline bağlı olarak, istediğiniz cevap -3 olacaktır. VB'de Doğru = -1.
Tom Collins


11
((a xor b) xor (c xor d)) and ((a or b) and (c or d))

Yumruk ifadesi true4'ten 1 veya 3'ü arar . İkincisi 0 veya 1'i (ve bazen 2) 4'ü ortadan kaldırır true.


11

Java 8, yanlış değerleri filtreleyin ve kalan gerçek değerleri sayın:

public static long count(Boolean... values) {
    return Arrays.stream(values).filter(t -> t).count();
}

Sonra aşağıdaki gibi kullanabilirsiniz:

if (3 == count(a, b, c, d)) {
    System.out.println("There... are... THREE... lights!");
}

Öğelerin doğru nolup olmadığını kolayca kontrol eder m.


11

En azından nhepsinin Booleandoğru olduğunu kontrol etmek için , (n toplam sayıdan küçük veya ona eşit olmalıdır Boolean: p)

if (((a ? 1:0) + (b ? 1:0 ) + (c ? 1:0) + (d ? 1:0 )) >= n) {
    // do the rest
}

Düzenleme : @ Cruncher'ın yorumundan sonra

boolean4 üzerinden 3 kontrol etmek için

if (((a ? 1:0) + (b ? 1:0 ) + (c ? 1:0) + (d ? 1:0 )) == 3) {
    // do the rest
}

Bir diğeri :

((c & d) & (a ^ b)) | ((a & b) & (c ^ d))( Ayrıntılar )


OP tam olarak n istiyor, en azından n değil. Ancak bu çözümden kolay bir değişiklik
Cruncher

2
@Wolf bu soru StackUnderflow.com aittir: p
bir hata değil

10

İşte LINQ ile C # ile çözmenin bir yolu:

bool threeTrue = new[] { a, b, x, y }.Count(x => x) == 3;

10

Simetrik Boole işlevi S₃(4) . Simetrik bir Boolean işlevi, yalnızca ayarlanan giriş miktarına bağlı olan, ancak hangi girdilere bağlı olmayan bir boolean işlevidir. Knuth, Bilgisayar Programlama Sanatı Cilt 4'teki 7.1.2 bölümünde bu tür işlevlerden bahseder.

S₃(4) aşağıdaki gibi 7 işlemle hesaplanabilir:

(x && y && (a || b)) ^ ((x || y) && a && b)

Bu normal operatörleri kullanarak en fazla 7 operasyonlarında bunu yapamaz yani optimum olduğunu Knuth gösterileri: &&, || , ^, <,ve> .

Ancak bunu 1doğru ve 0yanlış için kullanılan bir dilde kullanmak istiyorsanız, eklemeyi de kolayca kullanabilirsiniz:

x + y + a + b == 3

bu da niyetinizi oldukça netleştirir.


9
(a && b && (c xor d)) || (c && d && (a xor b))

Saf mantık açısından baktığım şey buydu.

Güvercin deliği prensibi ile, eğer tam olarak 3 doğruysa, ya a ve b doğrudur ya da c ve d doğrudur. O zaman bu davaların her birini tam olarak diğerinden biriyle ilişkilendirme meselesi 2.

Wolfram doğruluk tablosu


Bu, NameSpace'in ikinci çözümüne eşdeğerdir.
Brilliand

@Brilliand Benim için farklı görünüyor. Onun xor'ları hep birlikte 3'leri veya 1'leri almak için, daha sonra 2 ayrı gruptan en az bir tane isteyerek 1 olanları hariç tutar. (1 veya 3 ve en az 2 olarak özetlenmiştir). Benim hem farklı gruplardan birinden, hem de tam olarak diğer gruptan bir tanesini gerektirir.
Cruncher

Eğer bu anlamda bir eşdeğer demek istediyseniz, mine <=> hisbunun ne olacağını söyleyemem.
Cruncher

Sanırım bu cevap, NameSpace'in (önceki) cevabının kapsamadığı yeni bir şey eklemeden, NameSpace'in ikinci çözümüyle aynı şekilde iyi demekti. Neyse, oylarımı kaldıracağım.
Brilliand

8

Karnaugh Maps gibi bir mantık görselleştirme aracı kullanıyorsanız, bunun bir if (...) satırına yazmak istiyorsanız, tam gelişmiş bir mantık teriminden kaçınamayacağınız bir sorun olduğunu görürsünüz. Lopina zaten gösterdi, daha basit yazmak mümkün değil. Biraz dışarı katlayabilirsiniz, ancak sizin için VE makine için okumak zor kalacaktır.

Sayma çözümleri fena değil ve gerçekten neyin peşinde olduğunuzu gösteriyor. Sayımı nasıl verimli bir şekilde yapacağınız programlama dilinize bağlıdır. Python oder LinQ ile dizi çözümleri bakmak güzel, ama dikkat, bu YAVAŞ. Wolf'un (a + b + x + y) == 3 güzel ve hızlı çalışır, ancak yalnızca diliniz "true" 1 ile eşitse. "True" -1 ile temsil ediliyorsa, -3 için test etmeniz gerekir: )

Diliniz gerçek boolean kullanıyorsa, bunu açıkça programlamayı deneyebilirsiniz (I kullanıyorum! = XOR testi olarak):

if (a)
{
    if (b)
        return (x != y);    // a,b=true, so either x or y must be true
    else
        return (x && y);     // a=true, b=false, so x AND y must be true
}
else
{
    if (b)
        return (x && y);    // a=false, b=true, so x and y must be true
    else
        return false;       // a,b false, can't get 3 of 4
}

"x! = y" yalnızca x, y bir boole tipindeyse çalışır. 0'ın yanlış olduğu ve diğer her şeyin doğru olduğu başka bir türlerse, bu başarısız olabilir. Ardından, bir boole XOR veya ((bool) x! = (Bool) y) kullanın veya "x (return) (y == false) else return (y == true);" bilgisayar için çalışmak.

Programlama diliniz üçlü?: Operatörünü sağlıyorsa, dili kısaltabilirsiniz.

if (a)
    return b ? (x != y) : (x && y);
else
    return b ? (x && y) : false;

biraz okunabilirlik sağlar veya agresif bir şekilde keser.

return a ? (b ? (x != y) : (x && y)) : (b ? (x && y) : false);

Bu kod tam olarak üç mantık testi (a durumu, b durumu, x ve y karşılaştırması) yapar ve buradaki diğer cevapların çoğundan daha hızlı olmalıdır. Ama yorum yapmanız gerekiyor, ya da 3 ay sonra anlamayacaksınız :)


8

Burada birçok iyi cevap var; İşte henüz kimsenin göndermediği alternatif bir formülasyon:

 a ? (b ? (c ^ d) : (c && d)) : (b && c && d)

Cevabınız için teşekkür ederiz, ancak nasıl çalıştığına dair biraz yorum ekleyebilir misiniz? Teşekkürler.
Deanna

(Sizi seçtiğiniz için özür dilerim, bir inceleme denetimi olarak verildi. En azından ben geçtim .. :))
Deanna

7

İlk cevaba benzer, ancak saf Java:

int t(boolean b) {
    return (b) ? 1 : 0;
}

if (t(x) + t(y) + t(a) + t(b) == 3) return true;
return false;

Daha okunabilir kod için yapar çünkü onları tamsayı olarak saymayı tercih ederim.


7

In Python , elemanların bir iterable kaç tanesinin için vardır Doğru, kullanım sum(oldukça basittir):

Kurmak

import itertools

arrays = list(itertools.product(*[[True, False]]*4))

Gerçek Test

for array in arrays:
    print(array, sum(array)==3)

Çıktı

(True, True, True, True) False
(True, True, True, False) True
(True, True, False, True) True
(True, True, False, False) False
(True, False, True, True) True
(True, False, True, False) False
(True, False, False, True) False
(True, False, False, False) False
(False, True, True, True) True
(False, True, True, False) False
(False, True, False, True) False
(False, True, False, False) False
(False, False, True, True) False
(False, False, True, False) False
(False, False, False, True) False
(False, False, False, False) False

5

Kağıt üzerinde (programlama dışı) çözümün peşindeyseniz, K-haritaları ve Quine-McCluskey algoritmaları peşindeyseniz, boolean işlevinizi en aza indirmenize yardımcı olurlar.

Sizin durumunuzda, sonuç

y = (x̄3 ^ x2 ^ x1 ^ x0) ∨ (x3 ^ x̄2 ^ x1 ^ x0) ∨ (x3 ^ x2 ^ x̄1 ^ x0) ∨ (x3 ^ x2 ^ x1 ^ x̄0)

Bunu programlı olarak yapmak istiyorsanız, sabit olmayan değişken miktarı ve özel bir "eşik", o zaman basitçe bir boole değerleri listesi yinelemek ve "true" oluşumlarını saymak oldukça basit ve basittir.


1
Barın ek yükü ne anlama geliyor? Listenin aşağısında hareket ettiğini fark ettim.
NameSpace

3
@AdSpace İnsanların "değil" olarak ifade etmek için kullandıkları çok fazla gösterimden biridir.

5

Yalnızca 4 boole değerinden 3'ü doğruysa true döndürmek istiyorum.

A, b, x, y olmak üzere 4 boole değeri verildiğinde, bu görev aşağıdaki C ifadesine dönüşür:

return (a+b+x+y) == 3;

1
Güzel tuzak. Bu true, 1'e eşit kabul eder . Bu, tüm dillerde / durumlarda doğru değildir (cezalandırma amaçlı değildir). blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspx
JensG

@JensG Haklısın: Bu varsayımı açıkça belirtiyorum. Teşekkürler :)
Wolf

4
((a^b)^(x^y))&((a|b)&(x|y))

istediğin şey bu. Temelde kodunuzu aldı ve aslında 3 doğru ve 3 yanlış olup olmadığını kontrol ekledi.


4

Cevap içermeyen bir programlama sorusu özyineleme? Düşünülemez!

Yeterli "4 gerçekte tam 3" yanıtı var, ancak burada "tam olarak n gerçek dışı m" için genelleştirilmiş (Java) bir sürüm (aksi takdirde özyineleme gerçekten buna değmez):

public static boolean containsTrues(boolean[] someBooleans,
    int anIndex, int truesExpected, int truesFoundSoFar) {
  if (anIndex >= someBooleans.length) {
    return truesExpected == truesFoundSoFar; // reached end
  }
  int falsesExpected = someBooleans.length - truesExpected;
  boolean currentBoolean = someBooleans[anIndex];
  int truesFound = truesFoundSoFar + (currentBoolean ? 1 : 0);
  if (truesFound > truesExpected) {
    return false;
  }
  if (anIndex - truesFound > falsesExpected) {
    return false; // too many falses
  }
  return containsTrues(someBooleans, anIndex + 1, truesExpected,
      truesFound);
}

Bu, şöyle bir şeyle çağrılabilir:

 boolean[] booleans = { true, false, true, true, false, true, true, false };
 containsTrues(booleans, 0, 5, 0);

geri dönmelidir true(çünkü 8 değerden 5'i beklendiği gibi doğrudur). "True" ve "false" kelimelerinden pek memnun değil, ama şu anda daha iyi bir isim düşünemiyorum .... Çok fazla true veya çok fazla falsedeğer bulunduğunda özyinelemenin durduğunu unutmayın .


@ FélixSaparelli: "Gerçeğin" burada uygulandığından emin değilim ... sadece birinden memnun gibisin true. Belki böyle bir şey containsNumberOfTrueValues(). Bir yana: Smalltalk'ın isimlendirilmesi bunun için çok daha uygun olurdu doesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar. Muhtemelen bazı Java geliştiricilerinin zevkleri için çok uzun, ancak Smalltalkers hiçbir zaman uygun isimlendirmekten korkmaz ;-)
Amos M. Carpenter

Bu çoğunlukla mizahi idi. Ve containsTruthben oldukça iyidir inanıyoruz böylece araçlar, kelimenin tam anlamıyla, "gerçeğin bazı açıklanmayan miktarda içerir".
Félix Saparelli

3

Okunabilirlik büyük bir endişe kaynağı olduğundan, açıklayıcı bir işlev çağrısı kullanabilirsiniz (önerilen uygulamalardan herhangi birini sarma). Bu hesaplamanın birden fazla yerde yapılması gerekiyorsa, işlev çağrısı yeniden kullanımın en iyi yoludur ve tam olarak ne yaptığınızı netleştirir.

bool exactly_three_true_from(bool cond1, bool cond2, bool cond3, bool cond4)
{
    //...
}

3

PHP'de, onu daha dinamik hale getirme (koşul sayısını değiştirmeniz durumunda vb.):

$min = 6;
$total = 10;

// create our boolean array values
$arr = array_map(function($a){return mt_rand(0,1)>0;},range(1,$total));

// the 'check'
$arrbools = array_map(function($a){return (int)$a;},$arr);
$conditionMet = array_sum($arrbools)>=$min;

echo $conditionMet ? "Passed" : "Failed";

2
(((a AND b) OR (x AND y)) AND ((a XOR b) OR (x XOR y)))

Bunun iyi bir çözüm olduğunu gösterebilirken, Sam Hocevar'ın cevabını daha sonra yazmak ve anlamak kolaydır. Kitabımda bu daha iyi.


1

İşte bana ilham verdiğiniz için yazdığım bazı c # kodu:

Herhangi bir miktarda argüman alır ve size n doğru olup olmadığını söyler.

    static bool boolTester(int n, params bool[] values)
    {
        int sum = 0;           

        for (int i = 0; i < values.Length; i++)
        {
            if (values[i] == true)
            {
                sum += 1;
            }                
        }
        if( sum == n)
        {
            return true;
        }            
        return false;                
    }

ve şöyle diyorsunuz:

        bool a = true;
        bool b = true;
        bool c = true;
        bool d = false;            

        bool test = false;
        test = boolTester(3, a, b, c, d);

Böylece 7/9 veya 15/100'ü istediğiniz gibi test edebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.