Devrions-nous être amis?

30

Notez que cette question se concentre principalement sur

introduction

Bacefook veut que les gens soient plus amicaux! À ce titre, ils mettent en place un nouveau système pour proposer des amis! Votre tâche consiste à aider Bacefook à mettre en œuvre son nouveau système de suggestions.

Caractéristiques:

Votre programme doit être un REPL (boucle en lecture eval-print) supportant 3 types de commande: FRIEND, SUGGESTet KNOW.

FRIEND X Y- Spécifie cela Xet Ysont amis sur le réseau social.

  • Si X est ami avec Y, alors Y est ami avec X

  • Peut, mais ne doit pas avoir de sortie

  • X est toujours ami avec X

KNOW X Y - Produire une valeur véridique si X et Y sont amis, faux sinon

  • KNOW X X produira toujours une valeur véridique

SUGGEST X Y- Produire une valeur véridique si X et Y doivent être amis, faux sinon. X et Y devraient être amis si:

  • X et Y ne sont pas amis

  • X et Y ont au moins 1 ami en commun

Vous êtes autorisé à remplacer FRIEND, SUGGESTet KNOWavec vos propres chaînes, mais vous devez mentionner avec quelle chaîne vous avez remplacé chaque commande.

Votre programme peut accepter des entrées / produire des sorties de n'importe quelle manière, tant qu'il est raisonnablement facile de reconnaître son fonctionnement.

Le nombre de personnes dans le réseau social Nest compris entre 1 et 100 000, mais il peut exister un nombre illimité de «liens amis» (bords).

Si vous ne l'avez pas encore remarqué, il s'agit d'un problème de recherche de graphique. La structure de données (probablement) la plus simple (et peut-être la plus rapide) pour implémenter cela serait une matrice d'adjacence.

Cas de 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

Voici quelques cas de test supplémentaires sous forme d'image

Condition de victoire

C'est le , le code le plus court gagne!

Thunda
la source
Ainsi, par exemple, pouvons-nous commencer par entrer une liste de toutes les personnes du réseau, comme {A, B, C, D}?
Greg Martin
2
Il serait beaucoup plus utile d'avoir les cas de test sous forme de texte.
Greg Martin
1
Pouvons-nous avoir une sortie après la commande FRIEND?
2017
7
SUGGEST UK EU.
WBT
1
@Thunda en Python, l'utilisation du REPL intégré nécessite deux caractères supplémentaires dans la commande. Les langues comme celle-ci devraient-elles ajouter ces octets supplémentaires à la longueur totale du programme?
quintopie

Réponses:

44

SWI-Prolog, 62 47 41 octets

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

Prolog n'est pas trop souvent utile, mais quand c'est le cas, c'est tout simplement magnifique. Nous utiliserons a+bpour noter qui aest ami avec b, a*bqui asait bet a?bqui bdevrait être suggéré aou non. La première ligne indique simplement que X*Yest vrai si soit X+Y, Y+Xou X == Yest vrai. Cela met en œuvre la symétrie de se connaître. Demander s'il doit y avoir une suggestion est incroyablement simple. Nous demandons simplement s'il y en a un Zqui X*Yest faux X*Zet qui Y*Zest vrai. Exactement comme décrit dans le défi.

Si vous l'enregistrez en tant que fichier (par exemple friends.pl) et ouvrez SWI-Prolog avec ce fichier ( prolog -l friends.pl), vous obtenez déposé dans un REPL.

Vous pouvez affirmer des amitiés comme ceci:

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

Vous pouvez vérifier si les gens se connaissent ou une suggestion doit être faite:

'a'*'b'.
'a'?'d'.
orlp
la source
Vous devriez être en mesure d'enregistrer un tas d'octets remplaçant k(X,Y)avec X*Yet même avec fet en sutilisant différents opérandes. 21 octets si j'ai compté correctement.
Emigna
Je ne sais pas comment ils fonctionnent avec les assertions, donc je ne suis pas sûr f.
Emigna
12
Pète complètement à travers la structure de données en concevant une partie de la question. Incroyable.
Thunda
@Emigna Je l'ai implémenté, mais il n'a pas économisé autant que vous l'avez compté.
orlp
Je l'ai testé comme ça à 41 octets. Je n'ai pas de REPL pour l'essayer, donc je ne sais pas si cela fonctionne différemment là-bas.
Emigna
15

PHP, 138 133 129 octets

PHP bat Mathematica - une occurrence rare.

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));

imprime 1pour chaîne véridique et vide pour fausse. Exécutez-le -nrou testez-le en ligne .
nécessite PHP 7.1 pour l'affectation de liste; les noms d'utilisateur sont sensibles à la casse et exclure a, b, s.

panne

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 doit être rogné car il inclut le caractère de nouvelle ligne.
  • array_intersect_keydoit être mis en sourdine ou il donnerait des avertissements pour vide $$aou $$b.
  • +18 +15 octets pour tous les noms d'utilisateur: remplacez $$apar $f[$a]et $$bpar $f[$b].
Titus
la source
12

CMD (lot), 50 + 20 + 135 = 205 octets

  • FRIEND.CMD

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

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

    Impressions 1pour les amis, une ligne vierge pour les étrangers.

  • 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%
    

    Imprime 1ou une ligne vierge. Je pense que six %s consécutifs pourraient être un nouveau record personnel.

Neil
la source
C'est vraiment génial. Belle solution.
AdmBorkBork
6

Python 3, 122 118 + 2 = 120 octets

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'utilisation est exactement la même que la réponse d'Ovs.

orlp
la source
1
C'est assez évident pour moi, mais les exigences disent que vous devez spécifier comment utiliser votre REPL et avec quelles commandes. Peut être utile à ceux qui ne connaissent pas le python. (Incidemment, c'est exactement la méthode que j'aurais utilisée.)
quintopie
6

Python 3, 163 149 143 + 2 = 145 octets

-6 octets grâce à @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}

Enregistrez-le dans un fichier et exécutez-le sous python3 -i file.py
Utiliser
- f("a", "b")au lieu de FRIENDS a b
- k("a", "b")au lieu de KNOW a b
- s("a", "b")au lieu deSUGGEST a b

Sortie Falsey: 0, set (),
sortie False Truthy: ensemble non vide, True

Essayez-le en ligne


164 octets lorsque vous n'utilisez pas l'interpréteur python comme 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"])

Utilise
- fpour FRIEND
- spour SUGGEST
- autre chose pourKNOW

Essayez-le en ligne

ovs
la source
La fonction de suggestion est interrompue pour le deuxième lien
Thunda
@Thunda l'a corrigé
2017
Corrigez-moi si je manque quelque chose, mais au lieu de l.extend([(a,b),(b,a)]), ne pouvez-vous pas simplement le faire l+=[(a,b),(b,a)]? (Je n'ai pas encore testé cela)
HyperNeutrino
Oh désolé, j'ai réalisé mon erreur, qui cause un UnboundLocalError. Belle réponse d'ailleurs!
HyperNeutrino
si vous supprimez bool()de la sfonction, et utilisez 0, {}et Falsecomme Falsey et Trueet non vide setcomme Truthy, vous pourriez économiser 6 octets
Felipe Nardi Batista
5

Mathematica, 164 octets

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@##&

Définit trois fonctions principales F, Set Kavec le comportement souhaité. Par exemple, la séquence de commandes

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]

est le dernier cas de test de l'image liée dans l'OP; les Fcommandes ne produisent aucune sortie (le point-virgule unique semble un petit prix à payer pour cela), tandis que les six commandes SetK

True
True
False
False
True
True

comme voulu.

A tout moment, fla liste des couples de la forme {A, B}Asait B, alors que pla liste des personnes apparaissant dans un élément de f. L' appel F@{A, B}ajoute les quatre couples {A, B}, {B, A}, {A, A}et {B, B}à f.

Aussi, à tout moment, mest la matrice d'adjacence du graphe sous-jacent (une personne est adjacente à elle-même et à tous ses Famis); les lignes et les colonnes sont indexées par pet iconvertit une personne en numéro de ligne / colonne correspondant. La fonction d'assistance aprend une matrice et deux personnes comme entrées et recherche l'entrée de la matrice dont les «coordonnées» sont les deux personnes, renvoyant Truesi le nombre est positif et Falses'il est nul. (Il est également possible d'appeler alorsque l'une des personnes saisies n'est pas encore reconnue - par exemple, faire une requête KNOW ou SUGGEST avant toute déclaration FRIEND, ou poser des questions sur une pauvre personne qui n'a pas d'amis; cela génère des erreurs, mais la règle /._@__->0force la sortie à être de Falsetoute façon.)

L'appel K[A, B]recherche donc s'il m[A, B]est positif, ce qui implémente le Kverbe now. Le produit matriciel m.mest la matrice de longueur à 2 voies, contenant le nombre de façons de passer d'une personne à une autre le long d'une voie de longueur 2; cela permet S[A, B]d'implémenter le Sverbe uggest, tant que nous vérifions en outre à la main ( &&!K@##) que les personnes saisies ne se connaissent pas déjà.

Fait d'amusement: gratuit, cette mise en œuvre nous permet de déclarer les cliques d'amis-la commande F@{A, B, C, D}est équivalente à tous F@{A, B}, F@{A, C}, F@{A, D}, F@{B, C}, F@{B, D}et F@{C, D}combiné.

Greg Martin
la source
2

Python 2 , 118 octets

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

Essayez-le en ligne!

Comme je ne pouvais pas trouver d'outil de repl en ligne pour python 2, j'ai ajouté le TIO Nexus (au format REPL).

Requête pour option et sa sortie possible

0 pour Connu - Aucun

1 pour les amis - Vrai ou faux

2 pour Suggérer - Vrai ou Faux

Exemple d'utilisation et exemple de sortie dans un interpréteur python repl.

>>> 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
Keerthana Prabhakaran
la source
0

GNU sed , 158 + 2 (drapeaux rn) = 160 octets

Puisque sed est un langage basé sur des expressions rationnelles, il n'y a pas de types primitifs, sans parler des structures de données abstraites. Les données du réseau sont stockées sous forme de texte au format libre, dans ce cas sous forme de liens amis redondants comme A-B;B-A;etc., qui sont ensuite comparés à divers modèles d'expression régulière.

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

Essayez-le en ligne!

De par sa conception, sed exécute l'intégralité du script pour chaque ligne d'entrée. Je recommande de tester en mode interactif, pour voir la sortie d'une commande immédiatement après avoir tapé.

Utilisation: il n'y a pas de valeurs true / falsy dans sed, donc la convention de sortie que j'utilise est empruntée à bash, où une chaîne non vide est considérée comme véridique et une chaîne vide comme falsy.

  • F X Ypour FRIEND X Y. Il n'a pas de sortie.
  • K X Ypour KNOW X Y. Sorties «K» comme véridique, et rien comme fausse.
  • S X Ypour SUGGEST X Y. Sorties «S» comme véridique, et rien comme fausseté.

Explication:

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'.
seshoumara
la source