ปัญหา Ender ที่มีความสุข


32

ปัญหาสิ้นสุดความสุข (ที่จริงทฤษฎีบท) ระบุว่า

ชุดของห้าจุดใด ๆ ในเครื่องบินในตำแหน่งทั่วไปมีเซตย่อยของสี่จุดที่ก่อให้เกิดจุดยอดของรูปสี่เหลี่ยมนูน

ปัญหานี้ได้รับการตั้งชื่อโดย Paul Erd'sเมื่อนักคณิตศาสตร์สองคนที่ทำงานเกี่ยวกับปัญหานี้เป็นครั้งแรก Ester Klein และ George Szekeres เริ่มหมั้นและแต่งงานกันในภายหลัง

ชี้แจง:

  • ตำแหน่งทั่วไปที่นี่หมายความว่าไม่มีจุดสามจุดใด ๆ
  • รูปสี่เหลี่ยมที่เกิดขึ้นจากจุดยอดทั้งสี่จะได้รับการพิจารณาว่าไม่ตัดกันโดยไม่คำนึงถึงลำดับของคะแนน ตัวอย่างเช่นกำหนดสี่จุด[1 1], [1 2], [2 1], [2 2]รูปสี่เหลี่ยมตั้งใจเป็นตารางที่ไม่ได้ผูกโบว์:

    ป้อนคำอธิบายรูปภาพที่นี่

  • รูปสี่เหลี่ยมที่ไม่ตัดกันนั้นจะนูนถ้าไม่มีมุมภายในเกินกว่า 180 องศา; หรือเท่ากันถ้า diagonals ทั้งสองอยู่ภายในรูปสี่เหลี่ยม

ความท้าทาย

ให้ 5 คะแนนพร้อมพิกัดจำนวนเต็มบวกเอาท์พุท 4 ของคะแนนเหล่านั้นที่เป็นรูปสี่เหลี่ยมนูน

กฎระเบียบ

หากมีหลายวิธี (นั่นคือ 4 ชุดหลายชุด) คุณสามารถเลือกที่จะส่งออกหนึ่งหรือทั้งหมด

รูปแบบอินพุตและเอาต์พุตมีความยืดหยุ่นตามปกติ (อาร์เรย์รายการรายการของรายการสตริงที่มีตัวคั่นเหมาะสม ฯลฯ )

รหัสกอล์ฟน้อยที่สุดที่จะชนะ

กรณีทดสอบ

  1. การป้อนข้อมูล:

    [6 8] [1 10] [6 6] [5 9] [8 10]
    

    มีเพียงหนึ่งเอาต์พุตที่เป็นไปได้:

    [6 8] [1 10] [6 6] [5 9]
    
  2. การป้อนข้อมูล:

    [3 8] [7 5] [6 9] [7 8] [5 1]
    

    มีห้าวิธีแก้ไข:

    [3 8] [7 5] [6 9] [7 8]
    [3 8] [7 5] [6 9] [5 1]
    [3 8] [7 5] [7 8] [5 1]
    [3 8] [6 9] [7 8] [5 1]
    [7 5] [6 9] [7 8] [5 1]
    
  3. การป้อนข้อมูล:

    [4 8] [1 9] [9 9] [10 2] [1 6]
    

    มีสามวิธีคือ:

    [4 8] [1 9] [10 2] [1 6]
    [4 8] [9 9] [10 2] [1 6]
    [1 9] [9 9] [10 2] [1 6]
    

    เพื่อแสดงให้เห็นต่อไปนี้เป็นวิธีแก้ปัญหาสามกรณีนี้:

ป้อนคำอธิบายรูปภาพที่นี่


14
ฉันคาดหวังคำตอบจากมาร์ตินด้วยอารมณ์เชิงบวกที่แสดงในนั้น
El'endia Starman

1
ปัญหาที่สิ้นสุดความสุขไม่ได้ที่จะต้องวุ่นวายกับปัญหาพลิกความสุขซึ่งคือการหาวิธีการที่จะป้องกันไม่ให้ทหารเกณฑ์จากการค้นพบที่พวกเขาจำลองการเล่นกำลังเป็นจริง
253751

คำตอบ:


24

CJam, 37 34 32 ไบต์

{e!Wf<{2*3ew{)f.-~W%.*:-V>},!}=}

ไม่แน่ใจว่า:-Vมีความสุขเพียงพอหรือไม่ แต่อย่างที่จางจุนชี้ให้เห็นนั่นคือ=}จุดจบ :)

พิมพ์วิธีเดียวเท่านั้นเพราะการลบรายการที่ซ้ำกันออกจะมีราคาแพงกว่า

ทดสอบที่นี่

คำอธิบาย

ความคิดนั้นค่อนข้างง่าย เราสร้างรูปสี่เหลี่ยมที่เป็นไปได้ทั้งหมด (รวมถึงการเรียงลำดับของคะแนนทั้งหมด) จากนั้นเลือกรูปแบบนูน เราทดสอบความนูนโดยดูที่ขอบทุกคู่และตรวจสอบว่าพวกมันหมุนไปในทิศทางเดียวกัน

ความสามารถในการเลี้ยวสามารถหาได้ง่ายจากผลิตภัณฑ์จุด หากคุณใช้จุดสามจุดติดต่อกันบนรูปสี่เหลี่ยมและลากเส้นจากจุดแรกไปยังจุดที่สองและจุดที่หนึ่งไปยังจุดที่สามจากนั้นฉายหลังลงบนเส้นตั้งฉากของอดีต ... คุณจะได้รับจำนวนสัญญาณ ไม่ว่าจะเป็นสามจุดเหล่านี้เลี้ยวซ้ายหรือขวา (ฉันอาจจะเพิ่มไดอะแกรมสำหรับสิ่งนี้) "การคาดการณ์ลงบนฉากตั้งฉาก" นี้ฟังดูค่อนข้างเกี่ยวข้อง แต่จริงๆแล้วหมายความว่าเราย้อนกลับหนึ่งในสองเวกเตอร์และลบส่วนประกอบหลังจากการคูณแทนที่จะเพิ่มพวกมัน ดังนั้นนี่คือรหัส ...

e!       e# Generate all permutations of the five input points.
Wf<      e# Discard the fifth point in each permutations, giving all
         e# possible quadrilaterals.
{        e# Select the first for which this block gives a truthy result...
  2*     e#   Double the list of points, so that it includes each cyclically
         e#   adjacent set of three points.
  3ew    e#   Get all sublists of length 3, i.e. all sets of three consecutive
         e#   points (with two duplicates).
  {      e#   Filter these sets of three points...
    )    e#     Pull off the last point.
    f.-  e#     Subtract it from the other two, giving vectors from it to
         e#     to those.
    ~    e#     Unwrap the array dumping both vectors on the stack.
    W%   e#     Reverse one of them.
    .*   e#     Element-wise multiplication.
    :-   e#     Subtract the second element from the first. This completes
         e#     the projection.
    V>   e#     Check whether it's greater than 0. This is *false* for right-
         e#     turning sets of three points.
  },     e#   If all corners are right-turning, this will result
         e#   in an empty array.
  !      e#   Logical NOT - hence, only quadrilaterals where all corners
         e#   are right-turning give something truthy.
}=

2
แน่นอนว่าเป็ดที่มีความสุข!
Luis Mendo

1
@ LuisMendo ฉันคิดว่าตัวละครสองคนสุดท้ายดูเหมือนหน้ายิ้ม =}
K Zhang

!}ก็ถือว่าเป็นขยิบตาเช่นกัน
Jezzamon

2
Jon Skeet จาก CodeGolf .. มันช่างน่าอัศจรรย์
Alex Carlsen

8

MATLAB, 67 ไบต์

I=input('');for k=~eye(5);if nnz(convhull(I(k,:)))>4;I(k,:),end;end

อินพุตอยู่ในรูปแบบของเมทริกซ์ 2D โดยที่คอลัมน์คือ X และ Y ตามลำดับ:

[6 8; 1 10; 6 6; 5 9; 8 10]
[3 8; 7 5; 6 9; 7 8; 5 1]
[4 8; 1 9; 9 9; 10 2; 1 6]

ชุด 4 คะแนนทั้งหมดที่สร้าง quadrilaterals นูนจะแสดงในรูปแบบเดียวกัน

นี่คือตัวอย่างที่ได้รับการแก้ไขเล็กน้อยเพื่อให้ทำงานกับ Octave

คำอธิบาย

วิธีการแก้ปัญหานี้ใช้ชุดย่อยทั้งหมด 4 จุดของอินพุต (คำสั่งซื้อไม่สำคัญ) ~eye(5)การทำเช่นนี้เราจะสร้างเมทริกซ์เอกลักษณ์และปฏิเสธมัน เราวนรอบคอลัมน์ของเมทริกซ์นี้และk(ดัชนีลูป) เป็นอาร์เรย์แบบลอจิคัลซึ่งระบุว่าควรจะพิจารณา 4 จุดใด จากนั้นเราใช้สิ่งนี้เพื่อจับ 4 คะแนน XY เหล่านี้จากอินพุต ( I(k,:))

จากนั้นเราคำนวณเปลือกนูนของ 4 จุดเหล่านี้ ( convhull) เอาต์พุตของconvhullคือดัชนีของอินพุตที่สอดคล้องกับจุดที่ทำฮัลล์นูน (โดยดัชนีแรกทำซ้ำเพื่อปิดฮัลล์)

สำหรับรูปสี่เหลี่ยมนูนทั้งสี่จุดจะเป็นส่วนหนึ่งของตัวนูนของจุดเดียวกัน ( nnz(convhull(points)) > 4) หากเราตรวจพบว่าเป็นกรณีนี้เราจะแสดงจุดที่ใช้สำหรับการคำนวณซ้ำโดยเฉพาะ


4

Javascript (ES6), 306 293 283 ไบต์

c=(v,w,x)=>(w[0]-v[0])*(w[1]-x[1])-(w[1]-v[1])*(w[0]-x[0])>0?1:0
i=(v,w,x,y)=>(c(v,w,x)+c(w,x,y)+c(x,y,v)+c(y,v,w))%4==0&&r.push([v,w,x,y])
j=(v,w,x,y)=>{i(v,w,x,y);i(v,w,y,x);i(v,x,w,y)}
k=(v,w,x,y,z)=>{j(v,w,x,y);j(v,w,x,z);j(v,w,y,z);j(v,x,y,z);j(w,x,y,z)}
f=(v)=>(r=[],k(...v),r)

คำอธิบาย :

ฟังก์ชันcคำนวณผลิตภัณฑ์ไขว้ของเวกเตอร์ระหว่าง 3 จุดที่อยู่ติดกันของรูปหลายเหลี่ยมและส่งคืน 1 หากเป็นบวกและ 0 มิฉะนั้น (หมายเหตุ: ผลิตภัณฑ์ครอสไม่สามารถเป็นศูนย์ได้เนื่องจากจุดไม่สามารถร่วมเชิงเส้นได้)

j=(v,w,x,y)=>{i(v,w,x,y);i(v,w,y,x);i(v,x,w,y)}
k=(v,w,x,y,z)=>{j(v,w,x,y);j(v,w,x,z);j(v,w,y,z);j(v,x,y,z);j(w,x,y,z)}

ฟังก์ชั่นkและjสร้างการเรียงสับเปลี่ยนแบบวนรอบทั้งหมด (ละเว้นการกลับคำสั่ง) ของอาร์เรย์อินพุต

i=(v,w,x,y)=>(c(v,w,x)+c(w,x,y)+c(x,y,v)+c(y,v,w))%4==0&&r.push([v,w,x,y])

จากนั้นฟังก์ชั่น 'i' จะถูกเรียกใช้สำหรับการเปลี่ยนรูปแบบเป็นวงกลมในแต่ละครั้งเพื่อคำนวณผลรวมของฟังก์ชันcสำหรับพิกัดสามเท่าของพิกัดสามจุดที่อยู่ติดกัน หากผลิตภัณฑ์ครอสทั้งหมดมีเครื่องหมายเหมือนกันพวกเขาทั้งหมดจะเป็น 0 หรือ 1 และผลรวมเป็น 0 (โมดูโล 4) และรูปหลายเหลี่ยมนั้นเป็นส่วนเว้าและถูกผลักเข้าไปในอาร์เรย์เอาต์พุต หาก triplet ใด ๆ มีเครื่องหมายที่แตกต่างกันผลรวมจะไม่เป็นศูนย์ (modulo 4) และรูปหลายเหลี่ยมนูนออกมา

f=(v)=>(r=[],k(...v),r)

ฟังก์ชั่นที่fใช้ในการเริ่มต้นอาร์เรย์ออกแล้วเรียกฟังก์ชั่นดังกล่าวข้างต้นก่อนที่จะส่งกลับออก

การทดสอบ :

c=(v,w,x)=>(w[0]-v[0])*(w[1]-x[1])-(w[1]-v[1])*(w[0]-x[0])>0?1:0
i=(v,w,x,y)=>(c(v,w,x)+c(w,x,y)+c(x,y,v)+c(y,v,w))%4==0&&r.push([v,w,x,y])
j=(v,w,x,y)=>{i(v,w,x,y);i(v,w,y,x);i(v,x,w,y)}
k=(v,w,x,y,z)=>{j(v,w,x,y);j(v,w,x,z);j(v,w,y,z);j(v,x,y,z);j(w,x,y,z)}
f=(v)=>(r=[],k(...v),r)

tests = [
  [[6,8],[1,10],[6,6],[5,9],[8,10]],
  [[3,8],[7,5],[6,9],[7,8],[5,1]],
  [[4,8],[1,9],[9,9],[10,2],[1,6]]
];

tests.forEach(
  (test,i)=>{
    console.log( "Test " + (i+1) );
    f(test).forEach(
      (x)=>console.log( "  " + x.map((e)=>"("+e[0]+","+e[1]+")").join(','))
    );
  }
);

แก้ไข :

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

t=(a,b,c)=>Math.sign((b[0]-a[0])*(b[1]-c[1])-(b[1]-a[1])*(b[0]-c[0]))
p=(a,b,c,d)=>[t(a,b,c),t(b,c,d),t(c,d,a),t(d,a,b)].filter(x=>x).reduce((p,c,i,a)=>p&c==a[0],1)
q=(a,m,n,o)=>[a[0],a[m],a[n],a[o]]
f=(a)=>{r=[];for(i=0;i<5;i++){b=a.slice();b.splice(i,1);r.push(q(b,1,2,3));r.push(q(b,1,3,2));r.push(q(b,2,1,3))}return r.filter((a)=>p(...a))}

อย่างไรก็ตามเนื่องจากกรณีดังกล่าวได้รับการยกเว้นโดยเฉพาะในคำถามดังนั้นอักขระพิเศษจึงไม่จำเป็น


3

Mathematica 105 96 ไบต์

Select[#~Subsets~{4},f@#&]&เลือกจากรายการ (5) จุดย่อยบรรดา 4 fจุดที่ความพึงพอใจ

fเป็นที่พอใจเมื่อแต่ละจุดของ 4 จุดในชุดอยู่บนRegionBoundaryของConvexHullของ 4 จุด

f@p_:=Apply[And,RegionBoundary@ConvexHullMesh@p~RegionMember~#&/@p];
Select[#~Subsets~{4},f@#&]&

กรณีทดสอบ

1.ลองดูที่ 5 hulls ของเซตย่อย (แต่ละ 4 คะแนน) ของ {{6, 8}, {1, 10}, {6, 6}, {5, 9}, {8, 10}} .

Select[#~Subsets~{4},f@#&[{{6, 8}, {1, 10}, {6, 6}, {5, 9}, {8, 10}}]

{{{6, 8}, {1, 10}, {6, 6}, {5, 9}}}}


{{6, 8}, {1, 10}, {6, 6}, {5, 9}} เป็นทางออกเดียว แต่ละจุดสี่ทำหน้าที่เป็นจุดสุดยอดของเรือนูน (จาก 4 คะแนนเดียวกัน)

วิธีการแก้


{{6, 8}, {1, 10}, {6, 6}, {8, 10}} ไม่ใช่วิธีแก้ปัญหา ตัวเรือนูนมีเพียง 3 จุด {6, 8} อยู่ในตัวเรือ

fail1


เซ็ตย่อยที่เหลือยังไม่ใช่วิธีแก้ปัญหา:

fail2

fail3

fail4


2. {{4, 8}, {1, 9}, {9, 9}, {10, 2}, {1, 6}} มีวิธีแก้ปัญหาสามข้อ

Select[#~Subsets~{4},f@#&[{{4, 8}, {1, 9}, {9, 9}, {10, 2}, {1, 6}}]

{
{{4, 8}, {1, 9}, {10, 2}, {1, 6}},
{{4, 8}, {9, 9}, {10, 2}, {1, 6 }},
{{1, 9}, {9, 9}, {10, 2}, {1, 6}}
}


3. {{3, 8}, {7, 5}, {6, 9}, {7, 8}, {5, 1}} มี 5 โซลูชั่น

Select[#~Subsets~{4},f@#&[{{3, 8}, {7, 5}, {6, 9}, {7, 8}, {5, 1}}]

{
{{3, 8}, {7, 5}, {6, 9}, {7, 8}},
{{3, 8}, {7, 5}, {6, 9}, {5, 1 }},
{{3, 8}, {7, 5}, {7, 8}, {5, 1}},
{{3, 8}, {6, 9}, {7, 8}, {5 , 1}},
{{7, 5}, {6, 9}, {7, 8}, {5, 1}}
}}

โปรดทราบว่าแต่ละจุดห้าจุดนั้นอยู่ที่ขอบเขตของตัวเรือนูนของทุกจุด

หากจุดใดจุดหนึ่งถูกลบออกจุดที่เหลืออีก 4 จุดจะเป็นจุดยอดของตัวเรือนูนที่ลดลง

sol2

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