Come definire "o" logicamente


36

Di recente, ho riscontrato un problema che mi richiedeva di definire l'operatore logico "OR" a livello di codice, ma senza utilizzare l'operatore stesso.

Quello che mi è venuto in mente è questo:

OR(arg1, arg2)
  if arg1 = True and arg2 = True
     return True

  else if arg1 = True and arg2 = False
     return True

  else if arg1 = False and arg2 = True
     return True

  else:
     return False

Questa logica è corretta o mi sono perso qualcosa?


10
@gnat: Ad essere sinceri, una tabella di verità elenca gli output per ogni combinazione di input e l'articolo di Wikipedia fornisce una descrizione della funzione. Penso che quello che il PO è veramente chiedere è come definire un OR logico a livello di codice , senza l'utilizzo dell'operatore stesso.
Blrfl

6
@ user3687688 Potete per favore chiarire le primitive che siamo autorizzati a usare?
Fredoverflow,

4
questa domanda ha dato il via a uno spasmo collettivo di micro-ottimizzazione;)
Rob,

8
Potresti usare l'operatore ternarioreturn arg1 ? arg1 : arg2;
Matteo,

4
Devo sapere perché hai bisogno di ridefinire l' oroperatore.
Kyle Strand,

Risposte:


102

Direi che è corretto, ma non potresti condensarlo in qualcosa di simile?

or(arg1, arg2)
    if arg1 == true
        return true
    if arg2 == true
        return true

    return false

Dal momento che stai facendo un confronto o, non penso che tu debba davvero controllare la combinazione. Importa solo se uno di loro è vero per tornare vero. Altrimenti vogliamo restituire false.

Se stai cercando una versione più breve e meno dettagliata, funzionerà anche:

or(arg1, arg2)
    if arg1
        return arg1
    return arg2

6
Puoi anche rimuovere "else" alla riga 4 (lasciando solo if arg2 == true).
Dawson Toth,

1
@DawsonToth Ci sono molti modi in cui puoi ruotarlo, dipende se vuoi essere davvero verboso o condensato. Sarei contento dell'altro se, ma sembra che questa sia una domanda di pseudo codice, quindi probabilmente la lascerei così per chiarezza. Molto vero però!
Elliot Blackburn,

@BlueHat Sembra leggermente incoerente usare un altro se, ma non un altro alla fine.
SBoss,

1
@Mehrdad Grazie! Ho incluso la vecchia risposta solo perché ritengo che sia un po 'più dettagliata e spiega la soluzione un po' più chiara. Ma la tua soluzione è molto più piccola e fa lo stesso lavoro.
Elliot Blackburn,

1
ancora meglio (peggio):or(a, b): a ? a : b
Sara

149

Ecco una soluzione senza o, e, non, confronti e valori letterali booleani:

or(arg1, arg2)
  if arg1
    return arg1
  else
    return arg2

Probabilmente non è molto più fondamentale di così;)


32
+1 per una risposta leggermente più breve della mia. Tuttavia, sarei tentato di lasciar cadere anche "altro" solo per eleganza.
Elliot Blackburn,

10
@BlueHat Ma poi i due ritorni sarebbero rientrati in modo diverso;)
fredoverflow

5
Vorrei ottenere un EUR ogni volta che qualcuno confronta qualcosa con trueo false.
JensG,

1
@JensG Beh, da dove pensi che provengano le entrate di Bill Gates?
Kroltan,

1
||Operatore JavaScript in breve (se implementato in un linguaggio tipizzato in modo dinamico).
rinoceronte

108

Una riga di codice:

return not (not arg1 and not arg2)

Nessuna ramificazione, nessun OR.

In un linguaggio basato su C, sarebbe:

return !(!arg1 && !arg2);

Questa è semplicemente un'applicazione delle leggi di De Morgan :(A || B) == !(!A && !B)


6
Penso che questo approccio sia la soluzione migliore poiché (secondo me) un if/elsecostrutto è lo stesso dell'uso di OR, solo con un nome diverso.
Nick,

2
L'utilizzo di @Nick ifequivale all'uguaglianza. Normalmente nel codice macchina un ifviene implementato come aritmetica seguito da un confronto a zero con un salto.


1
Mi piace questo approccio perché cortocircuita i circuiti IFF and, fornendo così coerenza tra gli operatori.
Kyle Strand,

1
@Snowman È vero. Volevo dire che if (a) return true; else if (b) return true;sembra più o meno moralmente equivalente if (a OR b) return true;, ma tale punto di vista potrebbe benissimo essere oggetto di contestazione.
Nick,

13

Se hai solo ande not, puoi usare la legge di DeMorgan per girare and:

if not (arg1 = False and arg2 = False)
  return True
else
  return False

... o (ancora più semplicemente)

if arg1 = False and arg2 = False
  return false
else
  return true

...

E dal momento che apparentemente siamo tutti fissi sull'ottimizzazione di qualcosa che è quasi sempre disponibile come istruzione della macchina, ciò si riduce a:

return not(not arg1 and not arg2)

return arg1 ? true : arg2

ecc. ecc. ecc. ecc.

Poiché la maggior parte delle lingue fornisce un condizionale e, le probabilità sono l'operatore "e" implica comunque un ramo.

...

Se tutto ciò che hai è nand(vedi Wikipedia ):

return nand (nand (arg1, arg1), nand (arg2, arg2))


7
Semplifica:return not (not arg1 and not arg2)

@Snowman dovresti davvero fare una risposta per poter votare. Sei (attualmente) l'unico qui che non è andato con la ramificazione.
Lawtonfogle,

4
Stava per aggiungere la soluzione NAND, ma mi hai battuto. Tutto dovrebbe essere implementato in termini di NAND.
Andy,

2
@Andy: in realtà, tutto dovrebbe essere definito in termini di NOR. ;-)
Pieter Geerkens il

1
Buon lavoro con la nandsoluzione pura .
AAT

13

Funzioni (ECMAScript)

Tutto ciò che serve sono le definizioni delle funzioni e le chiamate di funzione. Non sono necessarie diramazioni, condizionali, operatori o funzioni incorporate. Dimostrerò un'implementazione usando ECMAScript.

Innanzitutto, definiamo due funzioni chiamate truee false. Potremmo definirli come vogliamo, sono completamente arbitrari, ma li definiremo in un modo molto speciale che presenta alcuni vantaggi, come vedremo più avanti:

const tru = (thn, _  ) => thn,
      fls = (_  , els) => els;

truè una funzione con due parametri che semplicemente ignora il suo secondo argomento e restituisce il primo. flsè anche una funzione con due parametri che semplicemente ignora il suo primo argomento e restituisce il secondo.

Perché abbiamo codificato true in flsquesto modo? Bene, in questo modo, le due funzioni non solo rappresentano i due concetti di truee false, no, allo stesso tempo rappresentano anche il concetto di "scelta", in altre parole, sono anche if/ then/ elseespressione! Valutiamo la ifcondizione e passiamo il thenblocco e il elseblocco come argomenti. Se la condizione viene valutata tru, verrà restituito il thenblocco, se viene valutato fls, restituirà il elseblocco. Ecco un esempio:

tru(23, 42);
// => 23

Questo ritorna 23e questo:

fls(23, 42);
// => 42

ritorna 42, proprio come ti aspetteresti.

C'è una ruga, tuttavia:

tru(console.log("then branch"), console.log("else branch"));
// then branch
// else branch

Questo stampa sia then branch e else branch! Perché?

Bene, restituisce il valore di ritorno del primo argomento, ma valuta entrambi gli argomenti, poiché ECMAScript è rigoroso e valuta sempre tutti gli argomenti in una funzione prima di chiamare la funzione. IOW: valuta il primo argomento che è console.log("then branch"), che semplicemente ritorna undefinede ha l'effetto collaterale della stampa then branchsulla console, e valuta il secondo argomento, che ritorna undefinede stampa anche sulla console come effetto collaterale. Quindi restituisce il primo undefined.

Nel calcolo λ, dove è stata inventata questa codifica, non è un problema: il calcolo λ è puro , il che significa che non ha effetti collaterali; pertanto non noteresti mai che anche il secondo argomento viene valutato. Inoltre, λ-calculus è pigro (o almeno, viene spesso valutato in ordine normale), il che significa che in realtà non valuta argomenti che non sono necessari. Quindi, IOW: nel calcolo λ il secondo argomento non verrebbe mai valutato, e se lo fosse, non lo noteremmo.

ECMAScript, tuttavia, è rigoroso , ovvero valuta sempre tutti gli argomenti. Bene, in realtà, non sempre: if/ then/ else, ad esempio, valuta il thenramo solo se la condizione è truee valuta il elseramo solo se la condizione è false. E vogliamo replicare questo comportamento con il nostro iff. Per fortuna, anche se ECMAScript non è pigro, ha un modo per ritardare la valutazione di un pezzo di codice, allo stesso modo quasi tutte le altre lingue: racchiudilo in una funzione, e se non la chiami mai, il codice non essere mai eseguito.

Quindi, avvolgiamo entrambi i blocchi in una funzione e alla fine chiamiamo la funzione che viene restituita:

tru(() => console.log("then branch"), () => console.log("else branch"))();
// then branch

stampe then branche

fls(() => console.log("then branch"), () => console.log("else branch"))();
// else branch

stampe else branch.

Potremmo implementare il tradizionale if/ then/ in elsequesto modo:

const iff = (cnd, thn, els) => cnd(thn, els);

iff(tru, 23, 42);
// => 23

iff(fls, 23, 42);
// => 42

Ancora una volta, abbiamo bisogno di alcune funzioni extra quando si chiama la ifffunzione e la funzione extra chiama parentesi nella definizione di iff, per lo stesso motivo di cui sopra:

const iff = (cnd, thn, els) => cnd(thn, els)();

iff(tru, () => console.log("then branch"), () => console.log("else branch"));
// then branch

iff(fls, () => console.log("then branch"), () => console.log("else branch"));
// else branch

Ora che abbiamo queste due definizioni, possiamo implementare or. Innanzitutto, oresaminiamo la tabella della verità per : se il primo operando è vero, allora il risultato dell'espressione è lo stesso del primo operando. Altrimenti, il risultato dell'espressione è il risultato del secondo operando. In breve: se il primo operando è true, restituiamo il primo operando, altrimenti restituiamo il secondo operando:

const orr = (a, b) => iff(a, () => a, () => b);

Diamo un'occhiata che funziona:

orr(tru,tru);
// => tru(thn, _) {}

orr(tru,fls);
// => tru(thn, _) {}

orr(fls,tru);
// => tru(thn, _) {}

orr(fls,fls);
// => fls(_, els) {}

Grande! Tuttavia, questa definizione sembra un po 'brutta. Ricorda, true flsgià agisci come un condizionale da solo, quindi davvero non ce n'è bisogno iff, e quindi tutta quella funzione che si avvolge affatto:

const orr = (a, b) => a(a, b);

Ecco qua: or(oltre ad altri operatori booleani) definiti con nient'altro che definizioni di funzione e chiamate di funzione in poche righe:

const tru = (thn, _  ) => thn,
      fls = (_  , els) => els,
      orr = (a  , b  ) => a(a, b),
      nnd = (a  , b  ) => a(b, a),
      ntt = a          => a(fls, tru),
      xor = (a  , b  ) => a(ntt(b), b),
      iff = (cnd, thn, els) => cnd(thn, els)();

Sfortunatamente, questa implementazione è piuttosto inutile: non ci sono funzioni o operatori in ECMAScript che restituiscono truo fls, tutti ritornano trueo false, quindi non possiamo usarli con le nostre funzioni. Ma c'è ancora molto che possiamo fare. Ad esempio, questa è un'implementazione di un elenco collegato singolarmente:

const cons = (hd, tl) => which => which(hd, tl),
      car  = l => l(tru),
      cdr  = l => l(fls);

Oggetti (Scala)

Potresti aver notato qualcosa di strano: true flssvolgono un doppio ruolo, agiscono sia come valori di dati trueche false, ma allo stesso tempo, fungono anche da espressione condizionale. Sono dati e comportamenti , raggruppati in un ... uhm ... "cosa" ... o (oserei dire) oggetto !

Anzi, true flssono oggetti. E, se hai mai usato Smalltalk, Self, Newspeak o altri linguaggi orientati agli oggetti, avrai notato che implementano i booleani esattamente allo stesso modo. Dimostrerò una tale implementazione qui a Scala:

sealed abstract trait Buul {
  def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): T
  def &&&(other:Buul): Buul
  def |||(other:Buul): Buul
  def ntt: Buul
}

case object Tru extends Buul {
  override def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): U = thn
  override def &&&(other:Buul) = other
  override def |||(other:Buul): this.type = this
  override def ntt = Fls
}

case object Fls extends Buul {
  override def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): V = els
  override def &&&(other:Buul): this.type = this
  override def |||(other:Buul) = other
  override def ntt = Tru
}

object BuulExtension {
  import scala.language.implicitConversions
  implicit def boolean2Buul(b:Boolean) = if (b) Tru else Fls
}

import BuulExtension._

(2 < 3) { println("2 is less than 3") } { println("2 is greater than 3") }
// 2 is less than 3

Questo BTW è il motivo per cui Sostituisci condizionale con polimorfismo Il refactoring funziona sempre: puoi sempre sostituire qualsiasi condizionale nel tuo programma con l'invio di messaggi polimorfici, perché come abbiamo appena mostrato, l'invio di messaggi polimorfici può sostituire i condizionali semplicemente implementandoli. Lingue come Smalltalk, Self e Newspeak ne sono la prova dell'esistenza, perché quelle lingue non hanno nemmeno i condizionali. (Inoltre, non dispongono di loop, BTW o di alcun tipo di strutture di controllo integrate nel linguaggio, ad eccezione dell'invio di messaggi polimorfici, ovvero chiamate di metodo virtuali.)


Pattern Matching (Haskell)

Puoi anche definire orusando la corrispondenza del modello, o qualcosa come le definizioni di funzione parziale di Haskell:

True ||| _ = True
_    ||| b = b

Naturalmente, la corrispondenza dei modelli è una forma di esecuzione condizionale, ma anche in questo caso lo è anche l'invio di messaggi orientato agli oggetti.


2
Che ne dici di False ||| False = Falsee _ ||| _ = Trueinvece? :)
fredoverflow il

3
@FredOverflow: ciò richiederebbe sempre di valutare l'operando giusto. Di solito gli operatori booleani dovrebbero essere non severi nella loro giusta argomentazione, nota anche come "corto circuito".
Jörg W Mittag,

Ah certo. Sapevo che doveva esserci un motivo più profondo :)
Fredoverflow,

La prima parte mi ha ricordato immediatamente la grande serie di Eric Lippert sullo stile del passaggio di continuazione . Semplicemente casuale ma comunque divertente :)
Voo

1
@ JörgWMittag La definizione di FredOverflow è opportunamente in corto circuito. True ||| undefinedMettiti alla prova in ghci per vedere!
Daniel Wagner,

3

Ecco un altro modo per definire OR, o addirittura qualsiasi operatore logico, usando il modo più tradizionale di definirlo: usare una tabella di verità.

Questo è ovviamente abbastanza banale da fare in linguaggi di livello superiore come Javascript o Perl, ma scrivo questo esempio in C per mostrare che la tecnica non dipende dalle caratteristiche del linguaggio di alto livello:

#include <stdio.h>

int main (void) {
    // Define truth table for OR:
    int OR[2][2] = {
        {0,   // false, false
         1},  // false, true
        {1,   // true, false
         1}   // true, true
    }

    // Let's test the definition
    printf("false || false = %d\n",OR[1==2]['b'=='a']);
    printf("true || false = %d\n",OR[10==10]['b'=='a']);

    // Usage:
    if (OR[ 1==2 ][ 3==4 ]) {
        printf("at least one is true\n");
    }
    else {
        printf("both are false\n");
    }
}

Puoi fare lo stesso con AND, NOR, NAND, NOT e XOR. Il codice è abbastanza pulito da sembrare una sintassi in modo da poter fare cose come questa:

if (OR[ a ][ AND[ b ][ c ] ]) { /* ... */ }

Penso che questo sia l'approccio "più puro" in un certo senso matematico. L'operatore OR è una funzione dopo tutto, e la tabella della verità è davvero l'essenza di quella funzione come relazione e insieme. Naturalmente questo potrebbe essere scritto anche in modo divertente OO:BinaryOperator or = new TruthTableBasedBinaryOperator(new TruthTable(false, true, true, true));
VIENI DAL

3

Un altro modo per esprimere gli operatori logici come espressioni aritmetiche intere (ove possibile). In questo modo è possibile evitare molte ramificazioni per un'espressione più ampia di molti predicati.

Let True be 1 Let False be 0

se la somma di entrambi è maggiore di 1, allora è vero o falso essere restituito.

boolean isOR(boolean arg1, boolean arg2){

   int L = arg1 ? 1 : 0;
   int R = arg2 ? 1 : 0;

   return (L+R) > 0;

}

6
booleanExpression ? true : falseè banalmente uguale a booleanExpression.
Appassionato il

Mi piace la tua metodologia, ma un semplice errore è che la somma di entrambi gli argomenti deve essere maggiore di ZERO per essere vera, non maggiore di ONE.
Grantly

1
return (arga+argb)>0
Grantly il

1
Stavo solo correggendo il tuo testo. Il tuo codice è perfetto, ma potrebbe essere in una riga: return (((arg1 ? 1 : 0)+(arg2 ? 1 : 0)) > 0); :)
Grantly il

1
@SenthuSivasambu Non ho obiezioni al tuo utilizzo di arg1 ? 1 : 0;. Quelle sono espressioni affidabili per trasformare un booleano in un numero. È solo la dichiarazione di ritorno che può essere banalmente riformattata.
Appassionato il

1

Le due forme:

OR(arg1, arg2)
  if arg1
     return True
  else:
     return arg2

O

OR(arg1, arg2)
  if arg1
     return arg1
  else:
     return arg2

Hanno il vantaggio simile al golf del codice di essere un po 'più piccolo degli altri suggerimenti finora, un ramo in meno. Non è nemmeno così sciocca una micro-opt per ridurre il numero di rami se stiamo considerando la creazione di un primitivo che sarebbe quindi molto usato.

La definizione di Javascript di ||è simile a questa, che combinata con la sua digitazione libera significa che l'espressione false || "abc"ha il valore "abc"e 42 || "abc"ha il valore 42.

Sebbene se hai già altri operatori logici, simili nand(not(arg1), not(arg2))potrebbero avere il vantaggio di non ramificarsi affatto.


a che serve ripetere la risposta precedente ( come hai ammesso )?
moscerino del

@gnat è abbastanza vicino che non mi sarei disturbato se avessi visto quella risposta, ma ha ancora qualcosa che non si trova in nessuno di essi, quindi lo sto lasciando.
Jon Hanna,

@gnat, in realtà considerando "Stiamo cercando risposte lunghe che forniscano una spiegazione e un contesto". Sono più felice con questa risposta ora.
Jon Hanna,

1

Oltre a tutte le soluzioni programmate usando if build, è possibile costruire un gate OR combinando tre gate NAND. Se vuoi vedere come è fatto su Wikipedia, clicca qui .

Da questo, l'espressione,

NOT [NOT (A AND A) AND NOT (B AND B)]

che utilizza NOT e AND fornisce la stessa risposta di OR. Si noti che l'uso di NOT e AND è solo un modo oscuro di esprimere NAND.


NOT (A AND A) == NOT (A)?
Charlie,

Si, esattamente. Nello stesso articolo di Wikipedia, puoi vedere come riducono una porta NOT alle porte NAND. Lo stesso per un cancello AND. Ho scelto di non modificare la formula presentata per il gate OR.
Walter Mitty,

1

Tutte le buone risposte sono già state date. Ma non lascerò che ciò mi fermi.

// This will break when the arguments are additive inverses.
// It is "cleverness" like this that's behind all the most amazing program errors.
or(arg1, arg2)
    return arg1 + arg2
    // Or if you need explicit conversions:
    // return (bool)((short)arg1 + (short)arg2)

In alternativa:

// Since `0 > -1`, negative numbers will cause weirdness.
or(arg1, arg2)
    return max(arg1, arg2)

Spero che nessuno avrebbe mai usato approcci come questi. Sono qui solo per promuovere la consapevolezza delle alternative.

Aggiornare:

Poiché i numeri negativi possono interrompere entrambi gli approcci di cui sopra, ecco un altro suggerimento terribile:

or(arg1, arg2)
    return !(!arg1 * !arg2)

Questo utilizza semplicemente le leggi di DeMorgan e abusa del fatto che *è simile a &&quando truee falsesono trattati come 1e 0rispettivamente. (Aspetta, stai dicendo che questo non è codice golf?)

Ecco una risposta decente:

or(arg1, arg2)
    return arg1 ? arg1 : arg2

Ma questo è essenzialmente identico ad altre risposte già fornite.


3
Questi approcci sono fondamentalmente imperfetti. Considera -1 + 1 per arg1+arg2, -1 e 0 per max(arg1,arg2), ecc.
Fluffy

@fluffy Questo approccio presuppone argomenti booleani e quindi funziona correttamente con la maggior parte dei tipi di immondizia. Bene da parte tua sottolineare che c'è ancora della spazzatura che produce problemi. Questo genere di cose è esattamente il motivo per cui dovremmo cercare di modellare il dominio del problema reale il più direttamente possibile (ed evitare di lasciarci trasportare dalla nostra intelligenza) nella pratica.
Appassionato il

Se stai eseguendo valori booleani a 1 bit puri, l'addizione non funziona ancora, poiché 1 + 1 = 0. :)
soffice

@fluffy È qui che entrano in gioco le conversioni esplicite. La necessità o meno dipende dai dettagli dell'implementazione (che è esattamente il motivo per cui questa è un'idea sciocca).
Appassionato il

0

Un modo per definire orè tramite una tabella di ricerca. Possiamo renderlo esplicito:

bool Or( bool a, bool b } {
  bool retval[] = {b,true}; // or {b,a};
  return retval[a];
}

creiamo un array con i valori che il valore restituito dovrebbe avere in base a ciò che aè. Quindi facciamo una ricerca. In C ++ come i linguaggi, boolpromuove un valore che può essere usato come indice di array, con trueessere 1e falseessere 0.

Possiamo quindi estenderlo ad altre operazioni logiche:

bool And( bool a, bool b } {
  bool retval[] = {false,b}; // or {a,b};
  return retval[a];
}
bool Xor( bool a, bool b } {
  bool retval[] = {b,!b};
  return retval[a];
}

Ora un aspetto negativo di tutti questi è che richiede la notazione del prefisso.

namespace operators {
  namespace details {
    template<class T> struct is_operator {};
    template<class Lhs, Op> struct half_expression { Lhs&& lhs; };
    template<class Lhs, class Op>
    half_expression< Lhs, Op > operator*( Lhs&&lhs, is_operator<Op> ) {
      return {std::forward<Lhs>(lhs)};
    }
    template<class Lhs, class Op, class Rhs>
    auto operator*( half_expression<Lhs, Op>&& lhs, Rhs&& rhs ) {
    return invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) );
    }
  }
  using details::is_operator;
}

struct or_tag {};
static const operators::is_operator<or_tag> OR;

bool invoke( bool a, or_tag, bool b ) {
  bool retval[] = {b,true};
  return retval[a];
}

e ora puoi digitare true *OR* falsee funziona.

La tecnica sopra descritta richiede un linguaggio che supporti la ricerca e i modelli dipendenti dall'argomento. Probabilmente potresti farlo in una lingua con generici e ADL.

A parte questo, puoi estendere quanto *OR*sopra per lavorare con i set. Basta creare una funzione gratuita invokenello stesso spazio dei nomi di or_tag:

template<class...Ts>
std::set<Ts...> invoke( std::set<Ts...> lhs, or_tag, std::set<Ts...> const& rhs ) {
  lhs.insert( rhs.begin(), rhs.end() );
  return lhs;
}

e ora set *OR* setrestituisce l'unione dei due.


0

Questo mi ricorda le funzioni charasteristic:

or(a, b)
    return a + b - a*b

Questo vale solo per le lingue che possono trattare i booleani come (1, 0). Non si applica a Smalltalk o Python poiché booleano è una classe. In smalltalk vanno ancora oltre (questo sarà scritto in una specie di pseudocodice):

False::or(a)
    return a

True::or(a)
    return self

E i doppi metodi esistono per e:

False::and(a)
    return self

True::and(a)
    return a

Quindi la "logica" è perfettamente valida nell'istruzione OP, sebbene sia dettagliata. Attenzione, non è male. È perfetto se hai bisogno di una funzione che agisce come un operatore matematico basato, per esempio, su una specie di matrice. Altri implementerebbero un cubo reale (come un'istruzione Quine-McCluskey):

or = array[2][2] {
    {0, 1},
    {1, 1}
}

E valuterai o [a] [b]

Quindi sì, ogni logica qui è valida (tranne quella pubblicata come usando l'operatore OR in lingua xDDDDDDDD).

Ma la mia preferita è la legge di DeMorgan: !(!a && !b)


0

Guarda la libreria standard di Swift e controlla la loro implementazione del collegamento OR e delle operazioni AND di collegamento, che non valutano i secondi operandi se non necessari / consentiti.


-2

La logica è perfettamente corretta, ma può essere semplificata:

or(arg1, arg2)
  if arg1 = True
     return True
  else if arg2 = True
     return True
  else
     return False

E presumibilmente la tua lingua ha un operatore OR così - a meno che non sia contro lo spirito della domanda - perché no

or(arg1, arg2)
  if arg1 = True or arg2 = True
     return True
  else
     return False

if arg1 = True or arg2 = True { return true } else { return false }Meglio ancora, return arg1 = True or arg2 = True. if condition then true else falseè ridondante.
Doval,

4
Asker ha specificamente sottolineato che il loro requisito era "senza usare l'operatore stesso"
moscerino del

2
Uhm, non ho detto niente del genere. Era un po 'quello che intendevo dire, ma la domanda non l'ha detto fino a quando non è stata modificata, e lei ha risposto come tale, così gentile da colpa mia.
logicNoob
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.