การรวมกันของหลายรายการ - อารัมภบท

ฉันจำเป็นต้องค้นหาชุดค่าผสมในรายการ ตัวอย่างเช่น ให้รายการต่อไปนี้

List = [[1, 2], [1, 2, 3]]

สิ่งเหล่านี้ควรเป็นผลลัพธ์

Comb = [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]

ตัวอย่างอื่น:

List = [[1,2],[1,2],[1,2,3]]

Comb = [[1,1,1],[1,1,2],[1,1,3],[1,2,1],[1,2,2],[1,2,3]....etc]

ฉันรู้วิธีดำเนินการกับรายการที่มีสองรายการย่อย แต่ต้องใช้ได้กับรายการย่อยจำนวนเท่าใดก็ได้

ฉันยังใหม่กับ Prolog โปรดช่วยด้วย


person Liuda Donic    schedule 07.03.2020    source แหล่งที่มา
comment
@GuyCoder: โซลูชันของคุณมีลักษณะอย่างไร   -  person false    schedule 08.03.2020
comment
@GuyCoder: ส่วนขยายใด ๆ ที่ใช้ระบบซึ่งตัวมันเองไม่สอดคล้องกันมากนักนั้นค่อนข้างน่าสงสัยอย่างแน่นอน ในกรณีที่เกิดปัญหา จะต้องปรึกษา Prolog ที่ขยายด้านล่าง   -  person false    schedule 08.03.2020
comment
@GuyCoder: คุณคิดว่านี่จะเป็นเรื่องง่ายสำหรับ OP หรือไม่?   -  person false    schedule 10.03.2020
comment
@GuyCoder: คำเตือน: คุณเสนอการแลกเปลี่ยน และฉันก็ทำส่วนของฉันสำเร็จ   -  person false    schedule 10.03.2020


คำตอบ (4)


คำตอบนี้ล่าเงินรางวัลที่เสนอ "สำหรับวิธีแก้ปัญหาที่แท้จริงซึ่งคำนึงถึง Ess ด้วย ที่นี่เราจะสรุป คำตอบก่อนหน้านี้ ดังนี้:

list_crossproduct(Xs, []) :-
   member([], Xs).
list_crossproduct(Xs, Ess) :-
   Ess = [E0|_],
   same_length(E0, Xs),
   maplist(maybelonger_than(Ess), Xs),
   list_comb(Xs, Ess).

maybelonger_than(Xs, Ys) :-
   maybeshorter_than(Ys, Xs).

maybeshorter_than([], _).
maybeshorter_than([_|Xs], [_|Ys]) :-
   maybeshorter_than(Xs, Ys).

list_crossproduct/2 ได้รับแบบสองทิศทางโดยเชื่อมโยง Xs และ Ess ก่อนเวลา

?- list_comb(Xs, [[1,2,3],[1,2,4],[1,2,5]]).
nontermination                                % BAD!

?- list_crossproduct(Xs, [[1,2,3],[1,2,4],[1,2,5]]).
   Xs = [[1],[2],[3,4,5]]      % this now works, too
;  false.

ตัวอย่างแบบสอบถามที่มีหลายคำตอบ:

?- list_crossproduct(Xs, [[1,2,3],[1,2,4],[1,2,5],X,Y,Z]).
   X = [1,2,_A],
   Y = [1,2,_B],
   Z = [1,2,_C], Xs = [[1],[2],[3,4,5,_A,_B,_C]]
;  X = [1,_A,3],
   Y = [1,_A,4],
   Z = [1,_A,5], Xs = [[1],[2,_A],[3,4,5]]
;  X = [_A,2,3],
   Y = [_A,2,4],
   Z = [_A,2,5], Xs = [[1,_A],[2],[3,4,5]]
;  false.
person repeat    schedule 23.03.2020
comment
สิ่งที่น่าสนใจ: ใช้ nilmemberd(Xs) แทน member([],Xs) ดีกว่า - person repeat; 26.03.2020

เพื่อความสมบูรณ์ นี่คือเวอร์ชันเสริมของเวอร์ชันความคิดเห็นของฉัน หมายเหตุ nilmemberd_t/2 ซึ่งได้รับแรงบันดาลใจจาก memberd_t/2

nilmemberd_t([], false).
nilmemberd_t([X|Xs], T) :-
   if_(nil_t(X), T = true, nilmemberd_t(Xs, T)).

nil_t([], true).
nil_t([_|_], false).

list_comb(List, []) :-
   nilmemberd_t(List, true).
list_comb(List, Ess) :-
   bagof(Es, maplist(member,Es,List), Ess).

เวอร์ชันด้านบนแสดงให้เห็นว่า "เฉพาะ" ประโยคแรกหายไปในการตอบกลับความคิดเห็นของฉัน อาจจะสั้นกว่านี้ด้วย:

nilmemberd([[]|_]).
nilmemberd([[_|_]|Nils]) :-
   nilmemberd(Nils).

สิ่งนี้ควรใช้ได้กับ Prologs โดยไม่มีข้อจำกัด ด้วยข้อจำกัด จะต้องพิจารณา bagof/3 ใหม่ เนื่องจากข้อจำกัดในการคัดลอกเป็นภูมิประเทศที่มีการกำหนดไว้ไม่ดี

person false    schedule 12.03.2020
comment
@rep: คุณหมายถึงคุณมีสิทธิ์ได้รับเงินรางวัลตามสัญญาใช่ไหม - person false; 13.03.2020
comment
ไม่นะ! แต่ฉันคิดว่าฉันควรโพสต์ตัวแปรแลมบ์ดาเป็นคำตอบแยกต่างหาก (แค่ 4 สนุกไม่ค่าหัว) - person repeat; 13.03.2020
comment
สมมุติว่าคุณทำสิ่งเหล่านี้ทั้งหมดแทนที่จะใช้ findall แทน bagof เพื่อหลีกเลี่ยงไม่ให้ findall( Es, maplist( member,Es, [[1,2],t,[1]]), Ess). ประสบความสำเร็จอย่างไม่ถูกต้องด้วย [] แทนที่จะล้มเหลว แต่เวอร์ชันของคุณก็ประสบความสำเร็จอย่างไม่ถูกต้องเช่นกันด้วย [] สำหรับ [[1,2],[],t,[1]] - person Will Ness; 23.03.2020
comment
ฉันหมายถึง เนื่องจาก bagof ล้มเหลวอย่างไม่ถูกต้องใน [[1,1],[],[1]] แต่ findall ถูกต้อง (ในกรณีนี้) ประสบความสำเร็จด้วย [] - person Will Ness; 23.03.2020
comment
@Will: bagof/3 จัดการตัวแปรอย่างถูกต้องในขณะที่ findall/3 คัดลอกพวกมันอย่างบ้าคลั่ง - person false; 23.03.2020
comment
list_comb(T,[[1]]). ลูปนั้นเป็นปัญหาน้อยกว่าตอนที่มันจะล้มเหลวมาก เนื่องจากการวนซ้ำไม่สามารถตีความได้ว่าเป็นจริงหรือเท็จ และสำหรับ list_comb([[1,2],[],t,[1]],X).: หากคุณเห็นว่าลักษณะทั่วไปนี้เป็นปัญหา เหตุใดคุณจึงเลือกที่จะประสบความสำเร็จสำหรับ list_comb([[1|non_list]],X) ด้วย สำหรับฉัน สิ่งนี้ถือว่ายอมรับได้ แต่ถ้าคุณยืนยัน โปรดใส่ maplist(maplist(\_^true), List) ที่ส่วนท้ายของกฎทั้งสอง - person false; 24.03.2020
comment
ฉันเพิ่งลอง list_comb( [[1 | t]], X ). ด้วยโค้ดของฉัน และ มันล้มเหลวอย่างถูกต้องตามที่คาดไว้ - person Will Ness; 26.03.2020
comment
@WillNess: เห็นด้วย - person false; 26.03.2020

ต่อไปนี้เป็นวิธีดำเนินการโดยใช้ maplist/3 และ append/2:

list_comb([], [[]]).
list_comb([Xs|Xss], Ess) :-
   Xs = [_|_],
   list_comb(Xss, Ess0),
   maplist(aux_x_comb(Ess0), Xs, Esss1),
   append(Esss1, Ess).

aux_x_comb(Ess0, X, Ess1) :-
   maplist(head_tail_list(X), Ess0, Ess1).

head_tail_list(X, Xs, [X|Xs]).

ข้อความค้นหาตัวอย่าง:

?- list_comb([[a,b],[f,g],[x,y,z]], Ess).
Ess = [[a,f,x],[a,f,y],[a,f,z],
       [a,g,x],[a,g,y],[a,g,z],
       [b,f,x],[b,f,y],[b,f,z],
       [b,g,x],[b,g,y],[b,g,z]].

นี่คือวิธีการทำงาน! เป็นตัวอย่าง ให้พิจารณาเป้าหมายเหล่านี้:

  • list_comb([[a,b],[f,g],[x,y,z]], Ess)

  • list_comb([ [f,g],[x,y,z]], Ess0)

เราจะได้ค่าจาก Ess0 ถึง Ess ได้อย่างไร?

  1. เราดูคำตอบของคำถามหลัง:

    ?- list_comb([[f,g],[x,y,z]], Ess0).
    Ess0 = [[f,x],[f,y],[f,z], [g,x],[g,y],[g,z]].
  2. ... วาง a ก่อน [f,x], ..., [g,z] ...

    ?- maplist(head_tail_list(a),
               [[f,x],[f,y],[f,z],
                [g,x],[g,y],[g,z]], X).
    X = [[a,f,x],[a,f,y],[a,f,z],
         [a,g,x],[a,g,y],[a,g,z]].

  3. ... จากนั้นทำเช่นเดียวกันกับ b

    maplist(aux_x_comb) ช่วยเราจัดการทุกรายการ:

    ?- maplist(aux_x_comb([[f,x],[f,y],[f,z],
                           [g,x],[g,y],[g,z]]),
               [a,b], X).
    X = [[[a,f,x],[a,f,y],[a,f,z],
          [a,g,x],[a,g,y],[a,g,z]],
         [[b,f,x],[b,f,y],[b,f,z],
          [b,g,x],[b,g,y],[b,g,z]]].

  4. หากต้องการรับจากรายการไปยังรายการให้ใช้ append/2

ฉันหวังว่าคำอธิบายนี้จะอธิบายได้ชัดเจนมากกว่าทำให้เกิดความสับสน :)

person repeat    schedule 12.03.2020
comment
Ess ไม่มีอิทธิพลต่อการยุติ - อย่างน้อยก็ในบางกรณี - person false; 17.03.2020

แนวทางของ @false ที่บิดเบี้ยว:

%list_comb( ++LL, -Ess)
list_comb( LL, Ess):-
    is_list( LL),
    maplist( is_list, LL),
    findall( Es, maplist( member, Es, LL), Ess).

การทดสอบ:

41 ?- list_comb( [[1,2],[1],[1]], X).
X = [[1, 1, 1], [2, 1, 1]].

42 ?- list_comb( [[1,2],[1],[1,2,3]], X).
X = [[1, 1, 1], [1, 1, 2], [1, 1, 3], [2, 1, 1], [2, 1, 2], [2, 1, 3]].

43 ?- list_comb( [[1,2],[],[1,2,3]], X).
X = [].

44 ?- list_comb( [[1,2],t,[1,2,3]], X).
false.

45 ?- list_comb( t, X).
false.
person Will Ness    schedule 23.03.2020
comment
เมื่อพิจารณาตัวแปรออก เพรดิเคตจะกลายเป็นโหมดเหมือนโปรแกรมเชิงฟังก์ชัน - แต่ไม่มี la... - เอ้อ - ไม่เข้มงวด - person false; 24.03.2020