Dovremmo essere amici?


30

Nota che questa è una domanda che si concentra principalmente sulle

introduzione

Bacefook vuole che le persone siano più amichevoli! Come tali, stanno implementando un nuovo sistema per suggerire amici! Il tuo compito è aiutare Bacefook a implementare il loro nuovo sistema di suggerimento.

specifiche tecniche:

Il vostro programma deve essere un REPL (loop lettura-valuta-stampa) che supporta 3 tipi di comandi: FRIEND, SUGGESTe KNOW.

FRIEND X Y- Specifica che Xe Ysono amici nel social network.

  • Se X è amico di Y, allora Y è amico di X

  • Può, ma non deve avere output

  • X è sempre amico di X

KNOW X Y - Emetti un valore veritiero se X e Y sono amici, falsa altrimenti

  • KNOW X X produrrà sempre un valore veritiero

SUGGEST X Y- Mostra un valore veritiero se X e Y dovessero essere amici, falsa altrimenti. X e Y dovrebbero essere amici se:

  • X e Y non sono amici

  • X e Y hanno almeno 1 amico in comune

Hai il permesso di sostituire FRIEND, SUGGESTe KNOWcon le proprie corde, ma si deve parlare di quello che stringa aver sostituito ogni comando con.

Il tuo programma può ricevere input / produrre output in qualsiasi modo desiderabile, purché sia ​​ragionevolmente facile riconoscere come funziona.

Il numero di persone nel social network Nè compreso tra 1 e 100.000, ma potrebbe esserci un numero qualsiasi di "link amici" (bordi).

Se non l'hai ancora notato, questo è un problema di ricerca del grafico. La struttura dei dati (probabilmente) più semplice (e forse più veloce) per implementarla sarebbe una matrice di adiacenza.

Casi test

FRIEND A B
FRIEND A C
FRIEND B D
SUGGEST A B -> Falsy, as they are friends
SUGGEST A D -> Truthy, as they share B as a common friend
SUGGEST C D -> Falsy, they do not share a common friend
KNOW D B -> Truthy, they are friends
KNOW B C -> Falsy, not friends
=============
FRIEND Tom Tim
KNOW Tom Tim -> Truthy
KNOW Tim Tom -> Truthy
KNOW Tom Kit -> Falsy
=============
KNOW Tim Kit -> Falsy
FRIEND Tim Tom
KNOW Tim Kit -> Falsy
FRIEND Tom Kit
SUGGEST Tim Kit -> Truthy
=============
FRIEND X Y
SUGGEST X Y -> Falsy since X is friends with X

Ecco alcuni altri casi di test in forma di immagine

Condizioni di vittoria

Questo è , vince il codice più corto!


Quindi, ad esempio, possiamo iniziare inserendo un elenco di tutte le persone nella rete, come {A, B, C, D}?
Greg Martin,

2
Avere i casi di test in forma di testo sarebbe molto più utile.
Greg Martin,

1
Possiamo avere un output dopo il comando FRIEND?
Ovs

7
SUGGEST UK EU.
WBT

1
@Thunda in Python, l'utilizzo del REPL integrato richiede due caratteri aggiuntivi nel comando. Lingue come questa dovrebbero aggiungere quei byte extra alla lunghezza totale del programma?
Quintopia,

Risposte:


44

SWI-Prolog, 62 47 41 byte

X*Y:-X+Y;Y+X;X==Y.
X?Y:-not(X*Y),X*Z,Y*Z.

Prolog non è spesso utile, ma quando è è semplicemente bello. Useremo a+bper notare che aè amico b, a*bche asa be a?bche bdovrebbe essere suggerito ao meno. La prima riga dice semplicemente che X*Yè vero se uno X+Y, Y+Xo X == Yè vero. Questo attua la simmetria di conoscersi. Chiedere se dovrebbe esserci un suggerimento è incredibilmente semplice. Chiediamo solo se esiste un Ztale che X*Yè falso X*Zed Y*Zè vero. Esattamente come descritto nella sfida.

Se lo salvi come file (ad es. friends.pl) E apri SWI-Prolog con questo file ( prolog -l friends.pl) verrai rilasciato in un REPL.

Puoi affermare amicizie come questa:

assert('a' + 'b').
assert('a' + 'c').
assert('b' + 'd').

Puoi verificare se le persone si conoscono o dovrebbero essere suggeriti:

'a'*'b'.
'a'?'d'.

Dovresti essere in grado di salvare un sacco di byte sostituendo k(X,Y)con X*Ye lo stesso con fe susando operandi diversi. 21 byte se ho contato correttamente.
Emigna,

Non sono sicuro di come funzionino con le asserzioni, quindi non sono sicuro f.
Emigna,

12
Completamente scorre attraverso la struttura dei dati progettando parte della domanda. Stupefacente.
Giovedì

@Emigna L'ho implementato, ma non ha risparmiato tanto quanto hai contato.
orlp

L'ho provato in questo modo a 41 byte. Non ho un REPL per provarlo, quindi non so se funziona diversamente lì.
Emigna,

15

PHP, 138 133 129 byte

PHP batte Mathematica - un evento raro.

for(;$s=fgets(STDIN);$s>G?print$$a[$b]?$s<L:$s>L&&@array_intersect_key($$a,$$b):$$a[$b]=$$b[$a]=1)[,$a,$b]=explode(" ",trim($s));

stampe 1per verità, stringa vuota per falsità. Esegui -nro prova online .
necessita di PHP 7.1 per l'assegnazione dell'elenco; nomi utente sono case sensitive e dovrebbero escludere a, b, s.

abbattersi

for(;$s=fgets(STDIN);                       # loop through input
    $s>G                                        # 2. evaluate command
        ?print$$a[$b]
            # command KNOW: true if $$a[$b]
            ?$s<L
            # command SUGGEST: true if !$$a[$b] and array_intersect_key returns truthy
            :$s>L&&@array_intersect_key($$a,$$b)
        # command FRIEND: set keys in $$a and $$b
        :$$a[$b]=$$b[$a]=1
)
    [,$a,$b]=explode(" ",trim($s));             # 1. parse user names to $a and $b
  • $s deve essere tagliato perché include il carattere di nuova riga.
  • array_intersect_keydeve essere disattivato o genererebbe avvisi per vuoto $$ao $$b.
  • +18 +15 byte per tutti i nomi utente: sostituire $$acon $f[$a]e $$bcon $f[$b].

12

CMD (batch), 50 + 20 + 135 = 205 byte

  • FRIEND.CMD

    @for %%f in (%1.%1 %1.%2 %2.%2 %2.%1)do @set %%f=1
    
  • KNOW.CMD

    @call echo(%%%1.%2%%
    

    Stampe 1per gli amici, una linea vuota per gli estranei.

  • SUGGEST.CMD

    @call set k=0%%%1.%2%%
    @set k=1&if %k%==0 for /f "tokens=2 delims=.=" %%f in ('set %1.')do @call set k=%%k%%%%%%f.%2%%
    @echo(%k:~1,1%
    

    Stampe 1o una linea vuota. Penso che sei secondi consecutivi %potrebbero essere un nuovo migliore personale.


È pazzesco fantastico. Bella soluzione.
AdmBorkBork

6

Python 3, 122 118 + 2 = 120 byte

l={}
def f(*r):l[r]=l[r[::-1]]=1
k=lambda a,b:a==b or(a,b)in l
s=lambda a,b:1-k(a,b)and any(k(a,z)&k(b,z)for z,_ in l)

L'uso è esattamente lo stesso della risposta di ovs.


1
È abbastanza ovvio per me, ma i requisiti dicono che è necessario specificare come utilizzare il REPL e con quali comandi. Può essere utile per coloro che non conoscono il pitone. (Per inciso, questo è esattamente il metodo che avrei usato.)
quintopia

6

Python 3, 163 149 143 + 2 = 145 byte

-6 byte grazie a @FelipeNardiBatista

l=[]
def f(a,b):l.extend([(a,b),(b,a)])
k=lambda a,b:a==b or(a,b)in l
s=lambda a,b:k(a,b)-1and{c for c,d in l if d==a}&{c for c,d in l if d==b}

Salvalo in un file ed eseguilo come python3 -i file.py
Usa
- f("a", "b")invece di FRIENDS a b
- k("a", "b")anziché KNOW a b
- s("a", "b")anzichéSUGGEST a b

Uscita Falsey: 0, set (),
uscita False Truthy: set non vuoto, True

Provalo online


164 byte quando non si utilizza l'interprete Python come REPL:

f=[]
while 1:c,a,b=input().split();i=(a,b)in f;f+=c=="f"and[(a,b),(b,a)]or[(i+(a==b),-i+1and{c for c,d in f if d==a}&{c for c,d in f if d==b})];print(f[-1][c=="s"])

Usa
- fper FRIEND
- sper SUGGEST
- qualsiasi altra cosa perKNOW

Provalo online


La funzione di suggerimento è interrotta per il secondo collegamento
Thunda

@Thunda risolto il problema
ovs

Correggimi se mi manca qualcosa, ma invece di l.extend([(a,b),(b,a)]), non puoi semplicemente farlo l+=[(a,b),(b,a)]? (Non l'ho ancora testato)
HyperNeutrino

Oh scusa, ho capito il mio errore, che provoca un UnboundLocalError. Bella risposta a proposito!
HyperNeutrino

se rimuovi bool()dalla sfunzione, e usi 0, {}e Falsecome Falsey e Truee un non vuoto setcome Truthy, potresti risparmiare 6 byte
Felipe Nardi Batista

5

Mathematica, 164 byte

f={}
p:=Union@@f
i=Position[p,#][[1,1]]&
m:=Outer[Boole@MemberQ[f,{##}]&,p,p]
a=(#[[i@#2,i@#3]]/._@__->0)>0&
F=(f=#~Tuples~2~Join~f;)&
K=m~a~##&
S=a[m.m,##]&&!K@##&

Definisce tre funzioni principali F, Se Kcon il comportamento desiderato. Ad esempio, la sequenza di comandi

F@{David, Bob}
F@{Bob, Alex}
F@{Alex, Kitty}
F@{Daniel, David}
F@{David, Kit}
S[David, Alex]
S[Bob, Kitty]
S[David, Kitty]
S[David, Bob]
K[David, Bob]
F@{Kit, Kitty}
S[David, Kitty]

è l'ultimo caso di test dall'immagine collegata nell'OP; i Fcomandi non producono alcun output (il punto e virgola singolo sembra un piccolo prezzo da pagare per questo), mentre i sei Se i Kcomandi producono

True
True
False
False
True
True

come desiderato.

In qualsiasi momento, fè l'elenco delle coppie ordinate del modulo {A, B}dove Asa B, mentre pè l'elenco delle persone che appare in qualche elemento di f. Chiamando F@{A, B}aggiunge le quattro coppie ordinate {A, B}, {B, A}, {A, A}, e {B, B}a f.

Inoltre, in qualsiasi momento, mè la matrice di adiacenza del grafico sottostante (una persona è adiacente a se stessa e a tutti i suoi Fprodigi); le righe e le colonne sono indicizzate da pe iconverte una persona nel corrispondente numero di riga / colonna. La funzione di supporto aprende una matrice e due persone come input e cerca l'ingresso della matrice le cui "coordinate" sono le due persone, restituendo Truese il numero è positivo e Falsese è zero. (È anche possibile chiamare aquando una delle persone di input non è ancora riconosciuta, ad esempio, fare una query KNOW o SUGGEST prima di qualsiasi dichiarazione FRIEND o chiedere a una persona povera che non ha amici; questo genera errori, ma la regola /._@__->0forza comunque l'output False.)

La chiamata K[A, B]quindi cerca se m[A, B]è positivo, il che implementa il Kverbo ora. Il prodotto matrice m.mè la matrice lunghezza-2-percorso, contenente il numero di modi per passare da una persona all'altra lungo un percorso di lunghezza 2; questo permette S[A, B]di implementare il Sverbo più brutto, purché controlliamo anche manualmente ( &&!K@##) che le persone di input non si conoscano già.

Curiosità: gratis, questa implementazione ci permette di dichiarare cricche di amici-comando F@{A, B, C, D}è equivalente a tutti F@{A, B}, F@{A, C}, F@{A, D}, F@{B, C}, F@{B, D}, e F@{C, D}combinato.


2

Python 2 , 118 byte

F=[]
def s(f,c):c=set(c);r=c in F;return F.append(c)if f%2 else not r^(4 in[len(x|c)for x in F])if f else 2>len(c)or r

Provalo online!

Dato che non sono riuscito a trovare lo strumento online di sostituzione per Python 2, ho aggiunto TIO Nexus (in formato REPL).

Richiedi l'opzione e il suo possibile output

0 per noto - Nessuno

1 per gli amici: vero o falso

2 per Suggerisci - Vero o Falso

Esempio di utilizzo e output di esempio in un interprete python sostitutivo.

>>> F=[]
>>> def s(f,c):c=set(c);r=c in F;return F.append(c)if f%2 else not r^(4 in[len(x|c)for x in F])if f else 2>len(c)or r
...
>>> s(1,['A','B'])
>>> s(1,['A','C'])
>>> s(1,['B','D'])
>>> s(2,['A','B'])
False
>>> s(2,['A','D'])
True
>>> s(2,['C','D'])
False
>>> s(0,['D','B'])
True
>>> s(0,['D','C'])
False

0

GNU sed , 158 + 2 (flag rn) = 160 byte

Poiché sed è un linguaggio basato sulla regex, non ci sono tipi primitivi, per non parlare delle strutture di dati astratte. I dati di rete vengono memorizzati come testo in formato libero, in questo caso come collegamenti amici ridondanti come A-B;B-A;ecc., Che viene quindi confrontato con vari schemi regex.

G
/^F/{s:. (.+) (.+)\n:\1-\1;\1-\2;\2-\1;\2-\2;:;h}
/^K |^S /{s:(.) (.+) (.+)\n.*\2-\3.*:\1:;/^K$/p}
/^S /s:(.) (.+) (.+)\n.*(.+)-(\2.*\4-\3|\3.*\4-\2).*:\1:p

Provalo online!

In base alla progettazione, sed esegue l'intero script per ogni riga di input. Consiglio di provare in modalità interattiva, per vedere l'output di un comando immediatamente dopo aver digitato.

Uso: non ci sono valori di verità / falsità in sed, quindi la convenzione di output che uso è presa in prestito da bash, per cui una stringa non vuota è considerata come vera, e una stringa vuota come falsa.

  • F X Yper FRIEND X Y. Non ha output.
  • K X Yper KNOW X Y. Produce "K" come verità e niente come falsità.
  • S X Yper SUGGEST X Y. Produce "S" come verità e niente come falsità.

Spiegazione:

G
# append stored network data, if any, to the current input line
/^F/{
# if command is 'F' (FRIEND), for ex. 'F X Y'
   s:. (.+) (.+)\n:\1-\1;\1-\2;\2-\1;\2-\2;:
   # generate friend links, for ex. 'X-X;X-Y;Y-X;Y-Y'
   h
   # store updated network data
}
/^K |^S /{
# if command is either 'K' (KNOW) or 'S' (SUGGEST), for ex. 'K X Y'
   s:(.) (.+) (.+)\n.*\2-\3.*:\1:
   # search friend link 'X-Y'. If found, delete pattern except the command letter.
   /^K$/p
   # if only letter K left, print it (command is 'K', 'X' and 'Y' are friends)
}
/^S /
# if command is 'S', for ex. 'S X Y', but 'X' and 'Y' aren't friends
   s:(.) (.+) (.+)\n.*(.+)-(\2.*\4-\3|\3.*\4-\2).*:\1:p
   # search if 'X' and 'Y' have a friend in common (for ex. 'C'), and if so print
   #letter S. The search is for ex. 'C-X.*C-Y' and 'C-Y.*C-X'.
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.