Alex ma czasem rację


50

Wyzwaniem jest podnieść na duchu naszego moda Alexa A. , który zwykle się myli .


Załóżmy, że masz przyjaciela o imieniu Alex, który potrzebuje pomocy w zakresie podstawowej logiki i matematyki, w szczególności równoważności matematycznej .

Daje ci listę równań formy, w [variable] = [variable]których a [variable]jest zawsze pojedynczą wielką literą od A do Z (nie małą literą, nie liczbą ani niczym innym). Na liście jest jedno równanie na linię z wyjątkiem jednej linii, która mówi tylko therefore.

Wszystkie równania powyżej thereforeprzesłankami , faktami, które uważa się za prawdziwe. Wszystkie równania poniżej thereforesą niezweryfikowanymi twierdzeniami, faktami, które Alex próbuje wywnioskować z przesłanek, i mogą być lub nie być prawdziwe.

Na przykład na tej liście równań A = Czdarza się, że jedna twierdzenie podsumowujące jest prawdziwe:

A = B
B = C
therefore
A = C

Twoim zadaniem jest powiedzieć Alexowi, czy wszystkie jego propozycje logicznie wynikają z danych przesłanek. Oznacza to, że musisz powiedzieć Alexowi, czy on się myli lub nie ma racji we wnioskach.

Napisz program / funkcję, która pobiera ciąg listy równań zgodnie z opisem i wypisuje / zwraca

Alex is right

jeśli wszystkie wnioski wynikają logicznie z przesłanek i w inny sposób wynikają

Alex is wrong

jeśli jakikolwiek wniosek nie wynika logicznie z przesłanek.

Najkrótszy kod w bajtach wygrywa.

Uważaj na te przypadki:

  • Zmienna zawsze jest równa sobie. na przykład

    B = A
    therefore
    A = A
    X = X
    

    powoduje w Alex is right.

  • Nie można zakładać, że zmienne o nieznanych relacjach są równe. na przykład

    P = Q
    therefore
    E = R
    

    powoduje w Alex is wrong.

  • Gdy po tym thereforeczasie nie ma równań, wnioski są bezsprzecznie prawdziwe . na przykład

    D = C
    therefore

    i

    therefore

    oba skutkują Alex is right.

  • Jeśli przedtem nie ma równań, thereforemożna wywnioskować tylko samowyrównanie. na przykład

    therefore
    R = R
    

    powoduje Alex is right, ale

    therefore
    R = W
    

    powoduje w Alex is wrong.

Więcej przykładów

Alex ma złe przypadki: (oddzielone pustymi liniami)

A = B
C = D
therefore
A = C

A = L
E = X
A = I
S = W
R = O
N = G
therefore
G = N
L = I
R = O
S = A
X = X
X = E

D = K
D = Q
L = P
O = L
M = O
therefore
K = L

A = B
therefore
B = C

Z = A
S = S
therefore
A = Z
A = A
S = A
A = S
Z = A
Z = A

K = L
K = X
therefore
X = P
L = X
L = P

therefore
A = B
B = C
A = C

therefore
A = A
B = B
C = C
D = D
E = E
F = F
G = G
H = H
I = I
J = J
K = K
T = I
L = L
M = M
N = N
O = O
P = P
Q = Q
R = R
S = S
T = T
U = U
V = V
W = W
X = X
Y = Y
Z = Z

A = B
B = C
C = D
D = E
E = F
F = G
G = H
H = I
I = J
J = K
K = L
L = M
M = N
N = O
O = P
P = O
Q = R
R = S
S = T
T = U
U = V
V = W
W = X
X = Y
Y = Z
therefore
A = Z

therefore
C = D
T = Y
A = Z

P = Q
therefore
E = R

therefore
R = W

Alex ma rację:

H = J
therefore
J = H

K = L
K = X
therefore
L = X

C = B
B = A
therefore
A = B

K = L
K = X
K = P
therefore
L = X
L = P
X = P

A = Y
Y = Q
Q = O
therefore
O = Y
O = A

C = C
therefore
C = C

A = B
B = A
therefore
A = B
B = A

A = B
B = C
C = D
therefore
A = A
A = B
A = C
A = D
B = A
B = B
B = C
B = D
C = A
C = B
C = C
C = D
D = A
D = B
D = C
D = D

therefore
A = A
B = B
C = C
D = D
E = E
F = F
G = G
H = H
I = I
J = J
K = K
L = L
M = M
N = N
O = O
P = P
Q = Q
R = R
S = S
T = T
U = U
V = V
W = W
X = X
Y = Y
Z = Z

D = I
F = H
J = M
therefore
M = J
D = I
H = F

A = B
B = C
C = D
D = E
E = F
F = G
G = H
H = I
I = J
J = K
K = L
L = M
M = N
N = O
O = P
P = Q
Q = R
R = S
S = T
T = U
U = V
V = W
W = X
X = Y
Y = Z
therefore
Z = A
F = R
G = I
W = L

A = B
B = C
therefore
A = C

B = A
therefore
A = A
X = X

P = P
C = G
M = C
therefore

D = C
therefore

therefore

therefore
R = R

42
PHP, 13 bajtów Alex is wrongWeryfikuje wszystkie przypadki testowe.
Dennis

19
Hej, czasem jest lepiej niż nigdy. ¯ \ _ (ツ) _ / ¯
Alex A.


7
therefore\nTABS < SPACES->Alex is right
Klamka

7
Uwielbiam widzieć rozwiązanie w prologu.
azz

Odpowiedzi:


18

CJam, 49

"Alex is "qN%S{f{)er}(_el-}h;{)#},"wrong""right"?

Inspirowany roztworem Ruby histocrata. Wypróbuj online
3 bajty zniszczone dzięki jimmy23013 :)

Wyjaśnienie:

Dla każdej przesłanki program zastępuje pierwszą zmienną drugą zmienną w pozostałej części tekstu. Następnie sprawdza, czy jest jakiś wniosek z różnymi zmiennymi.

"Alex is "    first push the part we know
qN%           read the input and split into lines
S             push a space (initial no-op replacement string, see below)
{…}h          do-while
  f{…}        for each line and the replacement string
    )         take out the last character
    er        replace the remaining character(s) with that character
  (           afterwards, take out the first line
  _el         duplicate and convert to lowercase
  -           remove all the resulting characters from the line
               this removes all lowercase letters and non-letters
               "X = Y" becomes "XY" (new replacement string)
               and "therefore" becomes "" (ending the loop)
              this is the loop condition and is left on the stack every time
;             after the loop, pop the empty string (from "therefore")
{…},          filter the remaining (conclusion) lines using the condition block
  )           take out the last character
  #           find its index in the remaining string
               this is 0 (false) iff the first character is the same as the last
              afterwards, we have an array of lines with non-equal variables
"wrong"       push "wrong"
"right"       push "right"
?             choose "wrong" if the array was not empty, else choose "right"

Stara wersja, 85

"Alex is "26,:A;{:i{{_A=_@-}g}%$~}:F;0q"= "-'t/Nf%~\{A\Ft:A;}/1>{F=}%-"right""wrong"?

Wykorzystuje algorytm znajdowania związku. Wypróbuj online


1
"Alex is "qN%S{f{)er}(_el-}h;{)#},"wrong""right"?.
jimmy23013

1
Właśnie przeczytałem ten ostatni wiersz jako „Używa algorytmu znajdowania jednorożca ”… czekaj? xD
Jan

Alex is * wrong * right * ?
Charlie

32

Rubin, 80 76 + 2 = 78

Z flagami wiersza poleceń p0uruchom

gsub$1,$2%p=$`[/e/]while~/(.) = (?!\1)(.)/
$_="Alex is #{p ?:wrong: :right}"

Wyjaśnienie:

Wykorzystuje to czystą manipulację ciągiem. p0wczytuje pełne dane wejściowe jako pojedynczy ciąg do zmiennej $_. Następnie wielokrotnie dopasowujemy ten ciąg do wyrażenia regularnego /(.) = (?!\1)(.)/, które znajduje wszystkie ciągi w postaci „X = Y”, gdzie X i Y nie są tą samą literą, i przypisuje X do 1 $, a Y do 2 $. Po znalezieniu takiego dopasowania gsub$1,$2zamienia wszystkie wystąpienia X na Y w ciągu. Sprawdzamy również, czy to dopasowanie wystąpiło przed czy po „zatem” z

$`[/e/]

Jeśli miało to miejsce później, jest to nieuzasadnione roszczenie, a Alex się myli. Śledzimy, czy takie zdarzenia wystąpiły przy użyciu p=. Zastosowanie pjako zmiennej śledzącej zapobiega pękaniu rzeczy, jeśli pętla nigdy nie trafi ani razu, ponieważ pzwróci zero, jeśli nigdy nie została przypisana.

Od tego postu rozwiązanie CJam jest dłuższe. Dumny, bez wątpienia ulotny moment.

Edycja: Tak, szybko zdetronizowany. Ponadto, aby zakończyć objaśnienie, z pflagą końcowa wartość $_jest wyprowadzana na końcu wykonywania, więc ostatni wiersz jest wyjściem.


15
Najsłodsze chwile to chwile, w których esolang zabija swoje rozwiązanie.
Alex A.,

Nadużywanie String#formatpołączenia zarówno połączenia gsub, jak i przypisania do jednego wyrażenia to całkiem fajny pomysł, +1!
Ventero

12

CJam, 83 75 68 67 64 bajtów

Dzięki Dennisowi za zaoszczędzenie 1 bajtu.

"Alex is "q_elN--N/:$La/~{)-},\{__m*{:&},::^|}5*-"wrong""right"?

Zestaw testowy. Przypadki testowe są zbyt długie, aby można było je połączyć bezpośrednio, więc po prostu skopiuj je z pytania. Zauważ, że jest to dość powolne - zajmuje on minutę lub dwie w tłumaczu online. Możesz zrobić to znacznie szybciej, zmieniając 5*na, 2*w którym przypadku zakończy się prawie natychmiast i rozwiąże wszystkie przypadki testowe oprócz jednego.

Wyjaśnienie

(Nieco przestarzałe.)

Chodzi o to, aby zrobić coś w rodzaju „wypełnienia zalewowego” możliwych równości, a następnie usunąć wszystkie równości, które uzyskaliśmy z listy wniosków. Można wykazać, że potrzebujemy nie więcej niż 5 kroków wypełnienia powodziowego, ponieważ obejmowałyby one odległość (na początkowym wykresie nierówności), ale maksymalną odległość wynosi 25.25 = 32

"Alex is " e# Push the string.
q          e# Read the input.
_elN-      e# Make a copy, convert to lower case, remove linefeeds. This gives us a string
           e# with all the characters we don't want from the input.
-          e# Remove them from the input. This leaves two upper-case letters on each line
           e# and an empty line between premises and conclusions.
N/         e# Split into lines.
La/        e# Split around the empty line.
~          e# Dump both halves on the stack.
{)-},      e# Remove any "A = A"-type equalities from the conclusions.
\          e# Swap with the premises.
{          e# Extend the premises 5 times...
  _Wf%     e#   Duplicate the premises and reverse each one, because = is symmetric.
  |        e#   Set union with the original premises.
  __m*     e#   Make two copies and get an array of every possible pair of premises.
  {:&},    e#   Select those which have at least one character in common.
  ::^      e#   For each such pair, take the mutual set difference, i.e. those characters
           e#   that are in only one of the strings.
  |        e#   Set union with the original premises.
}5*
-          e# Remove all the equalities we've obtained from the conclusions. If all
           e# conclusions were valid, the result will now be a empty array, which is falsy.
!          e# Logical not.
"wrong""right"?
           e# Select "wrong" or "right", respectively.

Konstruowanie zamknięcia przechodniego, co? Nie znam CJam, ale wygląda na to, że 5. generacja równości może być generowana tylko w jednym kierunku. Jeśli tak, potrzebujesz jeszcze jednej iteracji, aby odwrócić te równości.
user2357112

@ user2357112 Uważam, że powinny być generowane w obu kierunkach, ponieważ pierwszy krok dodaje wszystkie odwrotności danych wejściowych (lub w wersji, która jest bardziej golfowa, na początek sortuję wszystkie przesłanki i wnioski).
Martin Ender

Jeśli weźmiesz pod uwagę różnice symetryczne, czy uzyskasz krawędzie w obu kierunkach? (Lub, w wersji dla golfistów, czy różnice symetryczne powodują powstawanie krawędzi w wymaganym kierunku?)
user2357112,

@ user2357112 Ponieważ przetwarzam cały produkt kartezjański, otrzymam każdą parę równości w obu porządkach, co spowoduje obie kolejności wyciągniętych wniosków (jedynym powodem, dla którego muszę jawnie cofnąć lub posortować początkowe dane wejściowe, jest że pierwotne przesłanki niekoniecznie są generowane w tym procesie, więc nie można ich odwrócić, przyjmując ustawione różnice produktu kartezjańskiego).
Martin Ender

6

R 183 192 bajty

Zmodyfikowałem swoją odpowiedź, aby rozwiązać problem wskazany przez użytkownika2357112. Wciąż istnieje bardzo małe prawdopodobieństwo, że zadzwoni do Alexa, gdy ma on rację (co nie zdarza się często, jeśli rozumiem kontekst wyzwania :-). Mam nadzieję, że nie będzie miał nic przeciwko.

i=grep("t",z<-scan(,"",,,"\n"))
cat("Alex is",if(eval(parse(t=c(paste(LETTERS,"=",1:26),sample(rep(head(z,i-1),1e3)),paste(c(TRUE,sub("=","==",tail(z,-i))),collapse="&")))))"right"else"wrong")

Muszę to trochę de-golfować:

lines = scan(, what = "", sep = "\n")
therefore_idx = grep("therefore", lines)
setup = paste(LETTERS, "=", 1:26)
premises = sample(rep(head(lines, therefore_idx - 1), 1000))
propositions = paste(c(TRUE, sub("=", "==", tail(lines, -therefore_idx))), collapse = "&")
things_to_evaluate = c(setup, premises, propositions)
boolean_result = eval(parse(text = things_to_evaluate))
cat("Alex is", if (boolean_result) "right" else "wrong")

Na przykład, jeśli dane wejściowe to

A = B
B = C
therefore
A = C
B = C

najpierw oceni setup:

A = 1
B = 2
...
Z = 26

a później premises

A = B
B = C

będą uruchamiane 1000 razy w losowej kolejności. Ma to zapewnić („prawie pewność”), że wszystkie równości są propagowane. Na koniec oceni propositions:

TRUE & A == B & B == C

3
Jeśli przesłanki są A = B, B = C, C = A, wartości po prostu zmieniają się na zawsze. 26 rund oceny to za mało.
user2357112,

Moja nieudana logika ... Dzięki za przykład, będę musiał popracować nad czymś innym.
flodel

Myślę, że to naprawiłem, albo prawie ...!
flodel

5

Haskell, 208 bajtów

import Data.Equivalence.Persistent
c l=equate(l!!0)$last l 
r=foldr(c)$emptyEquivalence('A','Z')
l#r=equiv r(l!!0)$last l
f x|(h,_:t)<-span((<'t').head)$lines x="Alex is "++if all(#r h)t then"right"else"wrong"

Przenoszę pracę do Data.Equivalence.Persistentmodułu, który udostępnia funkcje do manipulowania klasami równoważności. Pozostaje tylko przeanalizować dane wejściowe i wywoływać funkcje, które czasem mają zbyt długie nazwy dla prawidłowego grania w golfa.

Przykład użycia:

*Main> f "A = B\nB = C\ntherefore\nA = C"
"Alex is right"

*Main> f "A = B\nB = D\ntherefore\nA = C"
"Alex is wrong"

3

Mathematica, 182

f[s_]:="Alex is "<>If[True===And@@Simplify[#2,#1]&@@(StringSplit[s,"\n"]/.{a___,"therefore",b___}:>StringSplit/@{{a},{b}}/.{x_,_,y_}:>Symbol[x<>"$"]==Symbol[y<>"$"]),"right","wrong"]

Działa na ciąg znaków, jak na wyzwanie.

In[]:= f["A = B
B = C
therefore
A = C"]
Out[]= Alex is right

In[]:= f["D = K
D = Q
L = P
O = L
M = O
therefore
K = L"]
Out[]= Alex is wrong

Możesz stracić 8 bajtów deklarując fjako czystej funkcji, zastępując Simplify[#2,#1]z #2~Simplify~#, i zastępowanie StringSplit[s,"\n"]z #~StringSplit~"<actual newline>".
LegionMammal978

Słuszne uwagi! Również, q=StringSplit;a następnie s / StringSplit / q / dla kolejnych 6 bajtów lub tak zapisanych. Ale w końcu obawiam się, że nie jest to dobre wyzwanie dla Mathematiki, mimo że logiczna postać wydawała się idealnie dopasowana.

Ponadto a___i b___prawdopodobnie można go zmienić na a__i b__, i s=Symbol;.
LegionMammal978

a__i b__nie będzie działać, jeśli przesłanki, propozycje lub oba będą puste

3

Siatkówka, 90 bajtów

Aby uruchomić, umieść następujące 12 wierszy kodu w 12 osobnych plikach (+11 bajtów zliczonych dla każdego pliku poza pierwszym). <empty>oznacza pusty plik; \noznacza dosłowną nową linię. Alternatywnie, zachowaj \ns takimi, jakie są, umieść wszystkie linie w jednym pliku i użyj -sopcji. Upewnij się, że wszystkie pliki używają dosłownych znaków nowej linii, a nie Windows \r\n, i zwróć uwagę na miejsce na końcu ostatniego wiersza.

s+`^(.) = (.)(.*)\1
$1 = $2$3$2
)`^. .+\n
<empty>
^.+|(.) = \1
<empty>
^\n*$
right
^[^r]+
wrong
^
Alex is 

Jak to działa

Pierwsza zamiana pasuje do pierwszej przesłanki w danych wejściowych, ilekroć lhs przesłanki występuje później w pliku. Zastępuje to późniejsze wystąpienie rhs przesłanki. +Modyfikator zapewnia, że wymiana jest powtarzany, aż nie pasuje do żadnego więcej. Tak więc, jeśli pierwszą przesłanką jest A = B, wszystkie kolejne As w pliku są przekształcane w Bs.

Druga zamiana usuwa pierwszą przesłankę z danych wejściowych, ponieważ skończyliśmy już teraz. Następnie )modyfikator zapętla się z powrotem do pierwszej zamiany i powtarza, dopóki nie nastąpi żadna zmiana w całym przejściu przez pętlę. Dzieje się tak, gdy wszystkie przesłanki zostały zastąpione i usunięte, a dane wejściowe zaczynają się od therefore.

Trzecie zastąpienie dopasowuje pierwszy wiersz danych wejściowych (który jest therefore) lub cokolwiek z formularza A = Ai usuwa je. Jeśli wszystkie propozycje są obsługiwane przez przesłanki, wszystkie będą pasować do tego formularza, więc to, co pozostanie, powinno składać się wyłącznie z nowych linii. Czwarta zamiana zmienia to na right. W przeciwnym razie piąta zamiana zmienia wszystko, co pozostało (które nie zawiera, rponieważ thereforezostało usunięte) na wrong. Wreszcie ostatnia wymiana dodaje Alex is na początku.


3

Python 2, 264 bajty

Istnieje już niezwykła odpowiedź na Python 3 autorstwa mbomb007 . Ta odpowiedź rażąco kradnie od tej (w szczególności sztuczka „Alex jest wrriognhgt”).

Ta odpowiedź jest również znacznie dłuższa niż ta ...

W każdym razie, w tej odpowiedzi chodzi o utrzymanie słownika par klucz-wartość, gdzie klucze to 26 wielkich liter, a odpowiadająca im wartość każdego klucza to zestaw liter, które są równoważne kluczowi. (Gdyby wszystkie 26 liter były równoważne, to każdy klucz miałby zestaw 26 liter odpowiadających im wartości.)

def a(s):
 d={C:set(C)for C in map(chr,range(65,91))};p,c=s.split('t');c,p=[x.split('\n')for x in[c[9:],p]]
 for u in p[:-1]:
    g,h=u[::4];y=d[g]|d[h]
    for v in y:
     for w in y:d[v]|=d[w];d[w]|=d[v]
 print'Alex is','wrriognhgt'[all(u[0]in d[u[4]]for u in c if u)::2]

(Aby zaoszczędzić bajty, ta odpowiedź miesza spacje i tabulatory , co jest dozwolone w Pythonie 2).

Ten kod jest naprawdę bardzo wydajny, ponieważ słownik jest ograniczony do maksymalnego możliwego rozmiaru (26 na 26, jak opisano powyżej), który nie zależy od liczby wierszy wejściowych.

Teraz, gdy grałem w golfa w tym rozwiązaniu, zdałem sobie sprawę, że mogę zapisać cztery bajty , używając ciągów zamiast zestawów wartości słownika, zastępując je

d={C:set(C)for C in map(

z

d={C:C for C in map(

Oczywiście musisz także zastąpić (UWAGA: NIE RÓB TO) trzema instancjami operacji ustawiania unii |z konkatenacją łańcuchów +, ale to nie zmienia długości kodu. Rezultat jest taki, że wszystko powinno nadal działać tak samo, z wyjątkiem tego, że nie eliminuje duplikatów, tak jak robisz to z setami (po prostu będzie dodawać na końcu łańcucha). Brzmi OK - pewnie trochę mniej wydajnie, ale 260 bajtów zamiast 264.

Okazuje się, że 260-bajtowa wersja jest tak nieefektywna , że spowodowała to, MemoryErrorgdy ją testowałem

A = B
A = B
therefore
B = A

To było dla mnie zaskakujące. Przeanalizujmy 260-bajtową wersję „konkatenacji łańcuchów”!

Oczywiście zaczynałoby się od par klucz-wartość A:Ai B:B(plus 24 innych, które nie mają znaczenia). Napiszemy, d[A]aby oznaczać wartość słownika odpowiadającą kluczowi A, więc na początku mielibyśmy d[A] = A. Teraz, biorąc pod uwagę założenie A = B, zacząłoby się od połączenia wartości d[A]=Ai d[B]=Bzdobycia y = AB. Następnie dwukrotnie zapętliłby ten ciąg: for v in AB: for w in AB:...

Więc po raz pierwszy w pętli mamy v=Ai w=A. Zastosowanie d[v] += d[w]i d[w] += d[v]wyniki w następującej sekwencji słowników:

{A:A, B:B}      (start)
{A:AA, B:B}     (d[A] += d[A])
{A:AAAA, B:B}     (d[A] += d[A])

Następnie za pomocą v=Ai w=B:

{A:AAAA, B:B}     (start)
{A:AAAAB, B:B}    (d[A] += d[B])
{A:AAAAB, B:BAAAAB}   (d[B] += d[A])

Następnie v=B, w=A:

{A:AAAAB, B:BAAAAB}   (start)
{A:AAAAB, B:BAAAABAAAAB}     (d[B] += d[A])
{A:AAAABBAAAABAAAAB, B:BAAAABAAAAB}     (d[A] += d[B])

I v=B, w=B:

{A:AAAABBAAAABAAAAB, B:BAAAABAAAAB}     (start)
{A:AAAABBAAAABAAAAB, B:BAAAABAAAABBAAAABAAAAB}     (d[B] += d[B])
{A:AAAABBAAAABAAAAB, B:BAAAABAAAABBAAAABAAAABBAAAABAAAABBAAAABAAAAB}     (d[B] += d[B])

Powyższa sekwencja kroków zaimplementowałaby jedną przesłankę A = B, z wnioskiem, który Ajest równy każdej literze w ciągu AAAABBAAAABAAAAB, a Brówny jest każdej literze w BAAAABAAAABBAAAABAAAABBAAAABAAAABBAAAABAAAAB.

Załóżmy teraz, że kolejna przesłanka jest A = B znowu . Najpierw obliczysz y = d[A] + d[B] = AAAABBAAAABAAAABBAAAABAAAABBAAAABAAAABBAAAABAAAABBAAAABAAAAB.

Następnie dwukrotnie zapętlamy ten ciąg: for v in y: for w in y:...

Tak. Może nie byłoby to bardzo skuteczne wdrożenie.


Moja odpowiedź nie jest „świetna”, ponieważ jest nieprawidłowa, ale była to godna uwagi próba. Szkoda, że ​​nie udało mi się go uruchomić.
mbomb007,

1
@ mbomb007 Huh, przykro mi to słyszeć. (Myślałem, że masz fajne podejście!) Ponieważ sprzeciwiłeś się słowu „świetnie”, zastąpiłem słowo „niezwykłe”. :)
matmandan

2

ES6, 128 bajtów

Luźno oparty na wersji Ruby.

r=s=>(m=/^[^e]*(.) = (?!\1)(.)/.exec(s))?r(s.replace(RegExp(m[1],'g'),m[2])):'Alex is '+(/(.) = (?!\1)/.test(s)?'wrong':'right')

Szuka jakiejkolwiek nierównouprawnienia przed „zatem” i za każdym razem zastępuje zmienną w całym ciągu (zapisuje to bajty w pętli while).


1

C, 240 bajtów

#define V[v-65]
v[26];char*r[]={"wrong","right"};i=65;j;g(a){return a V^a?g(a V):a;}main(){char b[16];for(;i<91;++i)i V=i;while(gets(b)&&*b<99)b[0]V=b[4]V=b[0]V<b[4]V?b[0]V:b[4]V;while(gets(b))j|=g(*b)^g(b[4]);printf("Alex is %s\n",r[!j]);}

Działa to poprzez łączenie wartości w zestaw drzew, więc wszelkie równoważne wartości prowadzą do tego samego katalogu głównego. Niegolfowane, z jawnymi typami niejawnymi.

// Anything before `V` becomes an index into `v`, offset by -'A'.
#define V [v-65]
int v[26];
char* r[] = {"wrong", "right"};
int i=65;
int j;
// Finds a set identifier for a by recursing until some index points to itself.
int g(int a) {
    return a V ^ a
           ? g(a V)
           : a;
}
int main() {
    char b[16];
    // Initialize all entries to point to themselves.
    for(; i < 91; ++i)
        i V = i;
    // For each premise "A = B", set the entries for A and B to point to the
    // smaller of their current values. This exits after reading "therefore"
    // as 't' > 99.
    while (gets(b) && *b < 99)
        b[0]V = b[4]V = b[0]V < b[4]V
                        ? b[0]V
                        : b[4]V;
    // For each conclusion "A = B", OR j with non-zero if the set identifiers
    // for A and B are different.
    while (gets(b))
        j |= g(*b) ^ g(b[4]);
    printf("Alex is %s\n", r[!j]);
}

180 bajtów

Ta krótsza wersja działa dla wszystkich przypadków z OP, ale w przypadku niektórych innych danych wejściowych niepoprawnie twierdzi, że Alex się myli. Wykorzystuje podobne podejście, ale dla każdej przesłanki po prostu ustawia drugi wpis na bieżącą wartość pierwszego wpisu. Porównując, szuka tylko dokładnych wartości zamiast wyszukiwania drzewa.

v[26];*V=v-65;char*r[]={"wrong","right"};i;j;main(){char b[16];for(;i<26;++i)v[i]=i;while(gets(b)&&*b<99)V[b[4]]=V[*b];while(gets(b))j|=V[*b]^V[b[4]];printf("Alex is %s\n",r[!j]);}

Przykładowe dane wejściowe, dla których to się nie udaje:

A = B
C = B,
dlatego
A = C


1

05AB1E , 32 bajty

…±º€ˆ „–у©#|€á[ćD.l#`:}\€ËPè«.ª

Zainspirowany odpowiedzią CJam @aditsu .

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

…±º€ˆ      # Push dictionary string "alex is "
„–у©      # Push dictionary string "wrong right"
     #     # Split by spaces: ["wrong","right"]
|          # Push all input-lines as list
 ۈ        # Only leave the letters of each line
   [       # Start an infinite loop:
    ć      #  Extract the head of the list; pop and push remainder-list and head separately
     D     #  Duplicate the head
      .l   #  If it's a lowercase string:
        #  #   Stop the infinite loop
    `      #  Push both letters in the string to the stack
     :     #  Replace all these letters in the remainder-list
 }\        # After the infinite loop: discard the duplicated "therefore"
          # For each letter-pair in the remainder list of condition-lines:
    Ë      #  Check if both letters are equal (1 if truhy; 0 if falsey)
   P       # Check if everything was truthy by taking the product
    è      # Use this to index into the earlier ["wrong","right"]-list
     «     # Append it to the "alex is " string
         # Sentence capitalize it
           # (after which the result is output implicitly)

Zobacz moją wskazówkę 05AB1E (sekcja Jak korzystać ze słownika? ), Aby zrozumieć, dlaczego …±º€ˆjest "alex is "i „–у©jest "wrong right".


0

bash + awk + SWI-Prolog , 167 bajtów

head -n1 <(awk '/therefore/{s=1;next};{if(s)print"?=("$1","$3")";else print};END{print"write(\"Alex is right\");write(\"Alex is wrong\"). halt."}' -|paste -sd ,|swipl)

Wypróbuj online!

Początkowo była to po prostu odpowiedź Prologa, ale narzędzia, które mogłem znaleźć, aby faktycznie przekształcić format wejściowy w coś użytecznego, były na tyle ograniczone, że zdecydowałem się wykonać tę część w bashu, chociaż nie miałem prawie żadnego doświadczenia robienie czegokolwiek w uderzeniu i nigdy nawet nie dotknęło awk. Skończyło się na tym, że spędziłem wystarczająco dużo godzin, aby opublikować go nawet po tym, jak wyrósł na ten 167-bajtowy, ledwo golfowy potwór.

Zasadniczo program awk pobiera dane wejściowe ze standardowego wejścia, usuwa linię z therefore, zastępuje A = Bpo nim ?=(A,B)i dołącza write(\"Alex is right\");write(\"Alex is wrong\"). halt.. Następnie paste -sd ,zastępuje każdy nowy wiersz, ale ostatni przecinkiem, przekształcając go w prawidłowe dwa zapytania do powłoki SWI-Prolog, które są następnie uruchamiane, a wydrukowany wynik jest obcinany do jednej linii head -n1, co wymaga <(...)zamiast potoku z przyczyn niezależnych moje zrozumienie. Wszystko po to, aby użyć wbudowanego !

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.