Chúng ta có nên làm bạn không?


30

Lưu ý đây là câu hỏi chủ yếu tập trung vào

Giới thiệu

Bacefook muốn mọi người thân thiện hơn! Vì vậy, họ đang thực hiện một hệ thống mới để đề xuất bạn bè! Nhiệm vụ của bạn là giúp Bacefook thực hiện hệ thống gợi ý mới của họ.

Thông số kỹ thuật:

Chương trình của bạn phải là một REPL (read-eval-in loop) hỗ trợ 3 loại lệnh: FRIEND, SUGGESTKNOW.

FRIEND X Y- Chỉ định rằng XYlà bạn bè trong mạng xã hội.

  • Nếu X là bạn với Y, thì Y là bạn với X

  • Có thể, nhưng không phải có đầu ra

  • X luôn là bạn với X

KNOW X Y - Xuất ra một giá trị trung thực nếu X và Y là bạn bè, nếu không thì giả

  • KNOW X X sẽ luôn tạo ra một giá trị trung thực

SUGGEST X Y- Xuất ra một giá trị trung thực nếu X và Y nên là bạn bè, giả mạo nếu không. X và Y nên làm bạn nếu:

  • X và Y không phải là bạn

  • X và Y có ít nhất 1 người bạn chung

Bạn được phép để thay thế FRIEND, SUGGESTKNOWvới chuỗi riêng của bạn, nhưng bạn phải đề cập đến những gì chuỗi bạn đã thay thế mỗi lệnh với.

Chương trình của bạn có thể nhận đầu vào / sản xuất đầu ra theo bất kỳ cách nào mong muốn, miễn là dễ dàng nhận ra cách thức hoạt động của nó.

Số người trong mạng xã hội Nlà từ 1 đến 100.000, nhưng có thể có bất kỳ số lượng "liên kết bạn bè" nào (các cạnh).

Nếu bạn chưa nhận thấy, đây là một vấn đề tìm kiếm đồ thị. Cấu trúc dữ liệu (có thể) dễ nhất (và có thể nhanh nhất) để thực hiện điều này sẽ là một ma trận kề.

Các trường hợp thử nghiệm

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

Dưới đây là một số trường hợp thử nghiệm khác ở dạng hình ảnh

Điều kiện thắng

Đây là , mã thắng ngắn nhất!


Vì vậy, ví dụ, chúng ta có thể bắt đầu bằng cách nhập danh sách tất cả mọi người trong mạng {A, B, C, D}không?
Greg Martin

2
Có các trường hợp thử nghiệm ở dạng văn bản sẽ hữu ích hơn.
Greg Martin

1
Chúng ta có thể có đầu ra sau lệnh FRIEND không?
trứng

7
SUGGEST UK EU.
WBT

1
@Thunda trong Python, sử dụng REPL tích hợp yêu cầu hai ký tự phụ trong lệnh. Các ngôn ngữ như thế này có nên thêm các byte bổ sung đó vào tổng chiều dài của chương trình không?
quintopia

Câu trả lời:


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 không quá thường xuyên hữu ích, nhưng khi nó chỉ đẹp. Chúng tôi sẽ sử dụng a+bđể ghi nốt đó alà kết bạn với b, a*babiết ba?brằng bnên được đề nghị ahay không. Dòng đầu tiên chỉ đơn giản nói rằng X*Ylà đúng nếu một trong hai X+Y, Y+Xhoặc X == Ylà đúng. Điều này thực hiện tính đối xứng của việc biết nhau. Hỏi nếu có một gợi ý là vô cùng đơn giản. Chúng tôi chỉ hỏi nếu có một cái Znhư vậy X*Ylà sai X*ZY*Zlà đúng. Chính xác như được mô tả trong thử thách.

Nếu bạn lưu tệp này dưới dạng tệp (ví dụ friends.pl) và mở SWI-Prolog với tệp này ( prolog -l friends.pl), bạn sẽ bị rơi vào REPL.

Bạn có thể khẳng định tình bạn như thế này:

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

Bạn có thể kiểm tra xem mọi người biết nhau hay đề xuất nên được thực hiện:

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

Bạn sẽ có thể lưu một loạt các byte thay thế k(X,Y)bằng X*Yvà giống với fssử dụng các toán hạng khác nhau. 21 byte nếu tôi đếm đúng.
Emigna

Không chắc chắn cách chúng hoạt động với các xác nhận mặc dù, vì vậy tôi không chắc chắn về f.
Emigna

12
Hoàn toàn xì hơi thông qua phần thiết kế cấu trúc dữ liệu của câu hỏi. Kinh ngạc.
Thunda

@Emigna Tôi đã triển khai nó, nhưng nó không tiết kiệm nhiều như bạn đã tính.
orlp

Tôi đã thử nghiệm nó như thế này ở 41 byte. Tôi không có REPL để thử mặc dù vậy tôi không biết nó có hoạt động khác ở đó không.
Emigna

15

PHP, 138 133 129 byte

PHP đánh bại Mathematica - một điều hiếm gặp.

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

in 1cho sự thật, chuỗi trống cho giả. Chạy với -nrhoặc kiểm tra nó trực tuyến .
cần PHP 7.1 để gán danh sách; tên người dùng là trường hợp nhạy cảm và cần loại trừ a, b, s.

phá vỡ

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 phải được cắt bớt vì nó bao gồm các ký tự dòng mới.
  • array_intersect_keyphải được tắt tiếng hoặc nó sẽ mang lại cảnh báo cho trống $$ahoặc $$b.
  • +18 +15 byte cho tất cả tên người dùng: Thay thế $$abằng $f[$a]$$bbằng $f[$b].

12

CMD (hàng loạt), 50 + 20 + 135 = 205 byte

  • BẠN B ..

    @for %%f in (%1.%1 %1.%2 %2.%2 %2.%1)do @set %%f=1
    
  • BIẾT.CMD

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

    In 1cho bạn bè, một dòng trống cho người lạ.

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

    In 1hoặc một dòng trống. Tôi nghĩ rằng sáu %s liên tiếp có thể là một cá nhân mới tốt nhất.


Điều đó thật tuyệt vời. Giải pháp tốt đẹp.
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)

Cách sử dụng hoàn toàn giống như câu trả lời của ovs.


1
Nó khá rõ ràng đối với tôi, nhưng các yêu cầu nói rằng bạn cần chỉ định cách sử dụng REPL của bạn và với các lệnh nào. Có thể hữu ích cho những người không biết trăn. (Ngẫu nhiên, đây chính xác là phương pháp mà tôi đã sử dụng.)
quintopia

6

Con trăn 3 163 149 143 + 2 = 145 byte

-6 byte nhờ @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}

Lưu nó vào một tệp và chạy nó dưới dạng python3 -i file.py
Sử dụng
- f("a", "b")thay vì FRIENDS a b
- k("a", "b")thay vì -KNOW a b
- s("a", "b")thay vì -SUGGEST a b

Đầu ra Falsey: 0, set (),
đầu ra sai Truthy: bộ không trống, True

Dùng thử trực tuyến


164 byte khi không sử dụng trình thông dịch python như 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"])

Sử dụng
- fcho FRIEND
- scho SUGGEST
- bất cứ điều gì khác choKNOW

Dùng thử trực tuyến


Chức năng đề xuất bị hỏng cho liên kết thứ hai
Thunda

@Thunda đã sửa nó
ovs

Chỉnh sửa cho tôi nếu tôi thiếu một cái gì đó, nhưng thay vì l.extend([(a,b),(b,a)]), bạn không thể làm gì l+=[(a,b),(b,a)]? (Tôi chưa thử nghiệm điều này)
HyperNeutrino

Ôi xin lỗi, tôi nhận ra sai lầm của mình, điều đó gây ra một UnboundLocalError. Nhân tiện trả lời tốt đẹp!
HyperNeutrino

nếu bạn xóa bool()khỏi shàm và sử dụng 0, {}Falsenhư Falsey và Truekhông trống setnhư Truthy, bạn có thể lưu 6 byte
Felipe Nardi Batista

5

Toán học, 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@##&

Xác ba chức năng chính F, SKvới hành vi mong muốn. Ví dụ: chuỗi các lệnh

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à trường hợp thử nghiệm cuối cùng từ hình ảnh được liên kết trong OP; các Flệnh không mang lại đầu ra (dấu chấm phẩy đơn có vẻ là một cái giá nhỏ phải trả cho việc này), trong khi các lệnh sáu SKlệnh mang lại

True
True
False
False
True
True

như mong muốn.

Tại bất kỳ thời điểm nào, flà danh sách các cặp được sắp xếp theo mẫu {A, B}Abiết B, trong khi đó plà danh sách những người xuất hiện trong một số yếu tố f. Gọi F@{A, B}thêm bốn cặp có thứ tự {A, B}, {B, A}, {A, A}, và {B, B}để f.

Ngoài ra, tại bất kỳ thời điểm nào, mlà ma trận kề của biểu đồ bên dưới (một người nằm liền kề với chính họ và với tất cả bạn bè của họ F); các hàng và cột được lập chỉ mục bởi pichuyển đổi một người thành số hàng / cột tương ứng. Hàm trợ giúp alấy một ma trận và hai người làm đầu vào và tra cứu mục nhập của ma trận có "tọa độ" là hai người, trả về Truenếu số đó dương và Falsenếu bằng không. ( aVí dụ, bạn cũng có thể gọi khi một trong những người đầu vào chưa nhận ra, sử dụng truy vấn KNOW hoặc SUGGEST trước bất kỳ tuyên bố FRIEND nào hoặc hỏi về một người nghèo không có bạn bè; điều này đưa ra lỗi, nhưng quy tắc /._@__->0buộc đầu ra là Falseanyway.)

Gọi K[A, B]do đó tìm kiếm cho dù m[A, B]là tích cực, mà thực Khiện động từ bây giờ. Sản phẩm ma trận là ma trận m.mđộ dài 2 đường dẫn, chứa số cách để đi từ người này sang người khác dọc theo đường dẫn có độ dài 2; điều này cho phép S[A, B]thực hiện Sđộng từ đề xuất, miễn là chúng tôi kiểm tra thêm bằng tay ( &&!K@##) rằng những người đầu vào không biết nhau.

Fun thực tế: miễn phí, thực hiện điều này cho phép chúng ta khai báo bè phái của bạn bè-lệnh F@{A, B, C, D}tương đương với tất cả F@{A, B}, F@{A, C}, F@{A, D}, F@{B, C}, F@{B, D}, và F@{C, D}cộng lại.


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

Hãy thử trực tuyến!

Vì tôi không thể tìm thấy công cụ thay thế trực tuyến cho python 2, tôi đã thêm TIO Nexus (ở định dạng REPL).

Truy vấn cho tùy chọn và đầu ra có thể của nó

0 cho Đã biết - Không có

1 cho bạn bè - Đúng hay Sai

2 cho Đề xuất - Đúng hoặc Sai

Ví dụ về việc sử dụng và đầu ra mẫu trong một trình thông dịch python thay thế.

>>> 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 (cờ rn) = 160 byte

Vì sed là một ngôn ngữ dựa trên regex, không có các kiểu nguyên thủy, không đề cập đến các cấu trúc dữ liệu trừu tượng. Dữ liệu mạng được lưu trữ dưới dạng văn bản định dạng miễn phí, trong trường hợp này là các liên kết bạn bè dư thừa như A-B;B-A;vv, sau đó được đối chiếu với các mẫu biểu thức chính quy khác nhau.

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

Hãy thử trực tuyến!

Theo thiết kế, sed chạy toàn bộ tập lệnh cho từng dòng đầu vào. Tôi khuyên bạn nên thử nghiệm trong chế độ tương tác, để xem đầu ra của lệnh ngay sau khi nhập.

Cách sử dụng: không có giá trị trung thực / giả trong sed, vì vậy quy ước đầu ra mà tôi sử dụng được mượn từ bash, theo đó, một chuỗi không trống được coi là trung thực và một chuỗi trống là giả.

  • F X Ycho FRIEND X Y. Nó không có đầu ra.
  • K X Ycho KNOW X Y. Kết quả 'K' là trung thực và không có gì sai lệch.
  • S X Ycho SUGGEST X Y. Đầu ra 'S' là trung thực và không có gì là giả.

Giải trình:

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'.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.