เราควรเป็นเพื่อนกันไหม


30

หมายเหตุนี่เป็นคำถามที่เน้นไปเป็นหลัก

บทนำ

Bacefook ต้องการให้ผู้คนเป็นมิตร! ดังนั้นพวกเขาจึงใช้ระบบใหม่เพื่อแนะนำเพื่อน! งานของคุณคือช่วย Bacefook ในการใช้ระบบแนะนำใหม่ของพวกเขา

ข้อมูลจำเพาะ:

โปรแกรมของคุณจะต้องเป็น REPL (ห่วงอ่าน EVAL-พิมพ์) สนับสนุน 3 ประเภทของคำสั่งFRIEND, และSUGGESTKNOW

FRIEND X Y- ระบุว่าXและYเป็นเพื่อนในเครือข่ายสังคมออนไลน์

  • ถ้า X เป็นเพื่อนกับ Y ดังนั้น Y คือเพื่อนกับ X

  • ทำได้ แต่ไม่จำเป็นต้องมีเอาต์พุต

  • X เป็นเพื่อนกับ X เสมอ

KNOW X Y - เอาท์พุทค่าความจริงถ้า X และ Y เป็นเพื่อนเท็จไม่อย่างนั้น

  • KNOW X X จะส่งออกค่าความจริงเสมอ

SUGGEST X Y- เอาท์พุทค่าความจริงถ้า X และ Y ควรเป็นเพื่อนไม่เช่นนั้นจะเป็นเท็จ X และ Y ควรเป็นเพื่อนถ้า:

  • X และ Y ไม่ใช่เพื่อน

  • X และ Y มีเพื่อนร่วมกันอย่างน้อย 1 คน

คุณได้รับอนุญาตเพื่อแทนที่FRIEND, SUGGESTและKNOWกับสตริงของคุณเอง แต่คุณจะต้องพูดถึงสิ่งที่คุณได้สตริงแทนที่แต่ละคำสั่งด้วย

โปรแกรมของคุณสามารถรับอินพุต / สร้างเอาต์พุตได้ตามที่ต้องการตราบใดที่ง่ายต่อการจดจำว่ามันทำงานอย่างไร

จำนวนคนในเครือข่ายโซเชียลNอยู่ระหว่าง 1 ถึง 100,000 แต่อาจมี "ลิงก์เพื่อน" (ขอบ) จำนวนเท่าใดก็ได้

หากคุณยังไม่ได้สังเกตนี่เป็นปัญหาการค้นหากราฟ โครงสร้างข้อมูล (น่าจะ) ที่ง่ายที่สุด (และอาจเร็วที่สุด) ที่จะใช้สิ่งนี้ในนั้นจะเป็นเมทริกซ์ adjacency

กรณีทดสอบ

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

นี่คือตัวอย่างทดสอบเพิ่มเติมในรูปแบบของภาพ

เงื่อนไขการชนะ

นี่คือรหัสที่สั้นที่สุดชนะ!


ตัวอย่างเช่นเราสามารถเริ่มต้นด้วยการป้อนรายชื่อของทุกคนในเครือข่ายได้{A, B, C, D}ไหม?
Greg Martin

2
มีกรณีทดสอบในรูปแบบข้อความจะเป็นประโยชน์มากขึ้น
Greg Martin

1
เราสามารถส่งออกหลังจากคำสั่งเพื่อน?
OVS

7
SUGGEST UK EU.
WBT

1
@Thunda ใน Python การใช้ REPL ในตัวต้องใช้อักขระพิเศษสองตัวในคำสั่ง ภาษาแบบนี้ควรเพิ่มจำนวนไบต์พิเศษเหล่านั้นให้ยาวรวมของโปรแกรมหรือไม่?
quintopia

คำตอบ:


44

SWI-Prolog, 62 47 41 ไบต์

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

อารัมภบทไม่ได้มีประโยชน์บ่อยนัก แต่เมื่อมันเป็นเพียงความสวยงาม เราจะใช้a+bเพื่อ notate ว่าaเป็นเพื่อนกับb, a*bที่aรู้bและa?bที่bควรได้รับการแนะนำให้aหรือไม่ บรรทัดแรกก็บอกว่าX*Yเป็นความจริงถ้าอย่างใดอย่างหนึ่งX+Y, Y+XหรือX == Yเป็นความจริง นี่เป็นการดำเนินการสมมาตรของการรู้จักกันและกัน การถามว่าควรมีข้อเสนอแนะหรือไม่นั้นง่ายมาก เราก็ถามว่ามีความเป็นไปZดังกล่าวว่าX*Yเป็นเท็จและX*ZและY*Zเป็นความจริง ตรงตามที่อธิบายไว้ในความท้าทาย

หากคุณบันทึกเป็นไฟล์ (เช่นfriends.pl) และเปิด SWI-Prolog ด้วยไฟล์นี้ ( prolog -l friends.pl) คุณจะถูกคัดลอกไปยัง REPL

คุณสามารถยืนยันมิตรภาพเช่นนี้:

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

คุณสามารถตรวจสอบว่าคนรู้ว่าแต่ละคนอื่นหรือควรทำข้อเสนอแนะ:

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

คุณควรจะสามารถบันทึกไบต์จำนวนมากแทนที่k(X,Y)ด้วยX*Yและเหมือนกันกับfและsใช้ตัวถูกดำเนินการที่แตกต่างกัน 21 ไบต์ถ้าฉันนับอย่างถูกต้อง
Emigna

fไม่แน่ใจว่าพวกเขาทำงานกับอ้างแม้ว่าดังนั้นฉันไม่แน่ใจ
Emigna

12
ผายลมโดยสิ้นเชิงผ่านโครงสร้างข้อมูลการออกแบบส่วนหนึ่งของคำถาม น่าอัศจรรย์
พฤหัสบดีที่

@Emigna ฉันได้ติดตั้งแล้ว แต่ก็ไม่ได้ช่วยอะไรมากเท่าที่คุณนับ
orlp

ฉันทดสอบมันแบบนี้ที่ 41 ไบต์ ฉันไม่มี REPL เพื่อลองใช้ แต่ฉันก็ไม่รู้ว่ามันใช้งานได้หรือไม่
Emigna

15

PHP, 138 133 129 ไบต์

PHP ชนะ Mathematica - เหตุการณ์ที่เกิดขึ้นได้ยาก

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

พิมพ์1เพื่อความจริงสตริงว่างสำหรับเท็จ ทำงานด้วย-nrหรือทดสอบออนไลน์
ต้องการ PHP 7.1 สำหรับการกำหนดรายการ ชื่อผู้ใช้เป็นกรณีที่สำคัญและควรแยกa, ,bs

ทำให้พังถล่ม

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 จะต้องมีการตัดแต่งเพราะมันมีตัวละครขึ้นบรรทัดใหม่
  • array_intersect_keyจะต้องมีการปิดเสียงหรือจะให้ผลผลิตคำเตือนสำหรับที่ว่างเปล่าหรือ$$a$$b
  • 18 15 ไบต์สำหรับชื่อของผู้ใช้ทั้งหมด: แทนที่$$aด้วย$f[$a]และมี$$b$f[$b]

12

CMD (แบทช์), 50 + 20 + 135 = 205 ไบต์

  • FRIEND.CMD

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

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

    พิมพ์1สำหรับเพื่อนบรรทัดว่างสำหรับคนแปลกหน้า

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

    พิมพ์1หรือบรรทัดว่าง ฉันคิดว่าหกติดต่อกัน%อาจเป็นเรื่องส่วนตัวที่ดีที่สุด


มันสุดยอดมาก ทางออกที่ดี
AdmBorkBork

6

Python 3, 122 118 + 2 = 120 ไบต์

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)

การใช้งานเหมือนกับคำตอบของ ovs


1
มันค่อนข้างชัดเจนสำหรับฉัน แต่ข้อกำหนดบอกว่าคุณต้องระบุวิธีใช้ REPL และคำสั่งอะไร อาจเป็นประโยชน์กับผู้ที่ไม่รู้จักงูหลาม (บังเอิญนี่เป็นวิธีที่ฉันจะใช้อย่างแน่นอน)
quintopia

6

Python 3, 163 149 143 + 2 = 145 ไบต์

-6 ไบต์ขอบคุณ @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}

บันทึกลงในไฟล์และเรียกใช้เป็นpython3 -i file.py
ใช้
- f("a", "b")แทนFRIENDS a b
- k("a", "b")แทนที่จะเป็นKNOW a b
- s("a", "b")แทนที่จะเป็น-SUGGEST a b

เอาต์พุต Falsey: 0, set (), False
Truthy output: ชุดที่ไม่ว่างเปล่า, True

ลองออนไลน์


164 ไบต์เมื่อไม่ได้ใช้ตัวแปลหลามเป็น 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"])

การใช้งาน
- fสำหรับFRIEND
- sสำหรับSUGGEST
- สิ่งอื่นใดสำหรับKNOW

ลองออนไลน์


ฟังก์ชั่นแนะนำใช้งานไม่ได้สำหรับลิงก์ที่สอง
Thunda

@Thunda แก้ไขแล้ว
ovs

แก้ไขให้ถูกต้องหากฉันทำบางสิ่งหายไป แต่แทนที่จะl.extend([(a,b),(b,a)])ทำl+=[(a,b),(b,a)]ไม่ได้ใช่ไหม (ฉันยังไม่ได้ทดสอบสิ่งนี้)
HyperNeutrino

UnboundLocalErrorโอ้ขอโทษฉันตระหนักถึงความผิดพลาดของฉันที่ทำให้เกิด คำตอบที่ดีโดยวิธี!
HyperNeutrino

หากคุณลบbool()จากsฟังก์ชั่นและการใช้งาน0, {}และFalseเป็น Falsey และTrueและไม่ว่างsetเป็น Truthy คุณสามารถบันทึก 6 ไบต์
เฟลิ Nardi บาติสตา

5

Mathematica, 164 ไบต์

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

กำหนดสามฟังก์ชั่นหลักF, SและKมีพฤติกรรมที่ต้องการ ตัวอย่างเช่นลำดับของคำสั่ง

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]

เป็นกรณีทดสอบสุดท้ายจากภาพที่เชื่อมโยงใน OP; Fคำสั่งให้ผลผลิตส่งออกไม่มี (อัฒภาคเดียวดูเหมือนว่าราคาขนาดเล็กจ่ายสำหรับการนี้) ในขณะที่หกSและKอัตราผลตอบแทนคำสั่ง

True
True
False
False
True
True

ตามที่ต้องการ

ในขณะใด ๆfคือรายการของคู่สั่งซื้อของแบบฟอร์ม{A, B}ที่Aรู้ว่าBในขณะที่เป็นรายชื่อของบุคคลที่ปรากฏในองค์ประกอบของบางคนp fโทรF@{A, B}เพิ่มสี่คู่สั่งซื้อ{A, B}, {B, A}, {A, A}และ{B, B}เพื่อfเพื่อ

ยิ่งไปกว่านั้นในเวลาใดก็ตามmเมทริกซ์คำคุณศัพท์ของกราฟพื้นฐาน (บุคคลอยู่ติดกับตัวเองและกับความสัมพันธ์ทั้งหมดF) แถวและคอลัมน์ถูกทำดัชนีโดยpและiแปลงบุคคลเป็นหมายเลขแถว / คอลัมน์ที่สอดคล้องกัน ฟังก์ชั่นตัวช่วยaใช้เมทริกซ์และคนสองคนเป็นอินพุตและค้นหารายการของเมทริกซ์ที่ "พิกัด" เป็นคนสองคนกลับมาTrueถ้าจำนวนเป็นบวกและFalseถ้าเป็นศูนย์ (อาจเป็นไปได้ที่จะโทรหาaเมื่อหนึ่งในคนอินพุตยังไม่ได้รับการยอมรับตัวอย่างเช่นการสอบถามแบบ KNOW หรือ SUGGEST ก่อนการประกาศเพื่อนหรือการถามเกี่ยวกับคนจนบางคนที่ไม่มีเพื่อนปัญหาข้อผิดพลาด แต่กฎ/._@__->0บังคับให้ส่งออกเป็นFalseอย่างไรก็ตาม)

K[A, B]ดังนั้นการโทรจึงดูว่าm[A, B]เป็นบวกหรือไม่ซึ่งใช้Kกริยาตอนนี้ ผลิตภัณฑ์เมทริกซ์m.mคือเมทริกซ์ความยาวเส้นทาง 2 ซึ่งบรรจุจำนวนวิธีที่จะเปลี่ยนจากบุคคลหนึ่งไปอีกคนหนึ่งตามเส้นทางยาว 2; สิ่งนี้ทำให้S[A, B]สามารถใช้Sกริยา uggest ได้ตราบใดที่เราตรวจสอบด้วยมือเพิ่มเติม ( &&!K@##) ว่าคนอินพุตไม่รู้จักซึ่งกันและกัน

สนุกจริง: ฟรี, การดำเนินงานนี้ช่วยให้เราสามารถ cliques ประกาศของเพื่อนคำสั่งF@{A, B, C, D}เทียบเท่ากับทุกF@{A, B}, F@{A, C}, F@{A, D}, F@{B, C}, F@{B, D}และF@{C, D}รวม


2

Python 2 , 118 ไบต์

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

ลองออนไลน์!

เนื่องจากฉันไม่พบเครื่องมือการทำสำเนาออนไลน์สำหรับ python 2 ฉันจึงเพิ่ม TIO Nexus (ในรูปแบบ REPL)

เคียวรีสำหรับอ็อพชันและเอาต์พุตที่เป็นไปได้

0 สำหรับเป็นที่รู้จัก - ไม่มี

1 สำหรับเพื่อน - จริงหรือเท็จ

2 สำหรับการแนะนำ - จริงหรือเท็จ

ตัวอย่างการใช้งานและตัวอย่างผลลัพธ์ในตัวแปลหลามแทน

>>> 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 (แฟล็ก rn) = 160 ไบต์

เนื่องจาก sed เป็นภาษาที่ใช้ regex จึงไม่มีชนิดดั้งเดิมที่ไม่พูดถึงโครงสร้างข้อมูลที่เป็นนามธรรม ข้อมูลเครือข่ายจะถูกจัดเก็บเป็นรูปแบบข้อความฟรีในกรณีนี้เป็นลิงก์เพื่อนซ้ำซ้อนเช่นA-B;B-A;ฯลฯ ซึ่งจะจับคู่กับรูปแบบ 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

ลองออนไลน์!

โดยการออกแบบ sed ทำงานสคริปต์ทั้งหมดสำหรับแต่ละบรรทัดอินพุต ฉันขอแนะนำให้ทดสอบในโหมดโต้ตอบเพื่อดูผลลัพธ์ของคำสั่งทันทีหลังจากพิมพ์

การใช้งาน:ไม่มีค่าจริง / เท็จใน sed ดังนั้นการประชุมเอาท์พุทที่ฉันใช้จะยืมมาจากทุบตีโดยสตริงที่ไม่ว่างถือว่าเป็นความจริงและสตริงว่างเปล่าเป็นเท็จ

  • F X Y สำหรับ FRIEND X Yสำหรับไม่มีเอาต์พุต
  • K X Y สำหรับ KNOW X Yสำหรับเอาท์พุท 'K' เป็นจริงและไม่มีอะไรเป็นเท็จ
  • S X YSUGGEST X Yสำหรับ เอาท์พุท 'S' เป็นความจริงและไม่มีอะไรเป็นเท็จ

คำอธิบาย:

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'.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.