একটি স্ব-আন্তঃখণ্ডিত বহুভুজের ক্ষেত্র


32

একটি সম্ভাব্য স্ব-ছেদকারী বহুভুজটি বিবেচনা করুন, 2D স্পেসের শীর্ষে অবস্থিত একটি তালিকা দ্বারা সংজ্ঞায়িত। যেমন

{{0, 0}, {5, 0}, {5, 4}, {1, 4}, {1, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 1}, {4, 1}, {4, 5}, {0, 5}}

এই জাতীয় বহুভুজের ক্ষেত্রটি নির্ধারণ করার জন্য বেশ কয়েকটি উপায় রয়েছে তবে সর্বাধিক আকর্ষণীয় একটি হচ্ছে সম-বিজোড় নিয়ম। বিমানের যে কোনও বিন্দু নিয়ে, বিন্দু থেকে অনন্ত (যে কোনও দিকে) দিকে একটি লাইন আঁকুন। যদি সেই রেখাটি বহুভুজকে একটি বিজোড় সংখ্যার বার অতিক্রম করে, তবে বিন্দুটি বহুভুজের ক্ষেত্রফলের অংশ, যদি বহুভুজটিকে বহুবার অতিক্রম করে, তবে বিন্দুটি বহুভুজের অংশ নয় of উপরোক্ত উদাহরণ বহুভুজের জন্য, এখানে এর বাহ্যরেখা পাশাপাশি এর সম-বিজোড় অঞ্চল উভয়ই রয়েছে:

রূপরেখাফোন

বহুভুজটি সাধারণত অরথোগোনাল হবে না। অঞ্চলটি গণনা করা আরও সহজ করার জন্য আমি কেবল এমন একটি সাধারণ উদাহরণ বেছে নিয়েছি।

এই উদাহরণের ক্ষেত্রটি হল 17(না 24বা 33অন্যান্য সংজ্ঞা বা ক্ষেত্রফল পেতে পারে)।

নোট করুন যে এই সংজ্ঞার অধীনে বহুভুজের ক্ষেত্রটি তার ঘুরানোর ক্রম থেকে পৃথক।

চ্যালেঞ্জ

বহুভুজকে সংজ্ঞায়িত করে পূর্ণসংখ্য স্থানাঙ্কের সাথে শীর্ষে অবস্থিত একটি তালিকা দেওয়া হয়েছে, এর ক্ষেত্রটি সম-বিচিত্র নিয়মের অধীনে নির্ধারণ করে।

আপনি STDIN বা নিকটতম বিকল্প, কমান্ড-লাইন আর্গুমেন্ট বা ফাংশন আর্গুমেন্টের মাধ্যমে ইনপুট নিয়ে কোনও ফাংশন বা প্রোগ্রাম লিখতে পারেন অথবা ফলাফলটি প্রত্যাবর্তন করতে পারেন বা এটি STDOUT বা নিকটতম বিকল্পে মুদ্রণ করতে পারেন।

আপনি যেকোন সুবিধাজনক তালিকা বা স্ট্রিং ফর্ম্যাটে ইনপুট নিতে পারেন, যতক্ষণ না এটি প্রাকপ্রসেসড নয়।

ফলটি হয় ভাসমান পয়েন্ট সংখ্যা, 6 টি গুরুত্বপূর্ণ (দশমিক) অঙ্কের সাথে সঠিক হওয়া বা একটি যুক্তিযুক্ত ফলাফল যার ভাসমান পয়েন্ট উপস্থাপনা 6 টি উল্লেখযোগ্য সংখ্যার সাথে সঠিক। (আপনি যদি যুক্তিসঙ্গত ফলাফল উত্পাদন করেন তবে সেগুলি সম্ভবত সঠিক হতে চলেছে, তবে রেফারেন্সের জন্য আমার সঠিক ফলাফল না পাওয়ায় আমার এটি প্রয়োজন হতে পারে না))

আপনি অবশ্যই একটি যুক্তিসঙ্গত ডেস্কটপ মেশিনে 10 সেকেন্ডের মধ্যে নীচের প্রতিটি পরীক্ষার কেস সমাধান করতে সক্ষম হবেন। (এই নিয়মের কিছুটা অবকাশ রয়েছে, সুতরাং আপনার সর্বোত্তম রায়টি ব্যবহার করুন my আমার ল্যাপটপে যদি এটি 20 সেকেন্ড সময় নেয় আমি আপনাকে সন্দেহের সুবিধা দেব, যদি এটি এক মিনিট সময় নেয় তবে আমি করব না)) আমি মনে করি এই সীমাটি খুব উদার হওয়া উচিত তবে আপনি কেবলমাত্র পর্যাপ্ত সূক্ষ্ম গ্রিড এবং গণনাতে বহুভুজকে বিচ্ছিন্ন করতে বা মন্টি কার্লোর মতো সম্ভাব্য পন্থাগুলি ব্যবহার করার উপায়গুলি অস্বীকার করার কথা। একজন ভাল খেলোয়াড় হন এবং এই পদ্ধতির অনুকূলিতকরণের চেষ্টা করবেন না যাতে আপনি যেভাবে সময় সীমা পূরণ করতে পারেন। ;)

আপনি বহুভুজ সরাসরি সম্পর্কিত কোন বিদ্যমান ফাংশন ব্যবহার করা উচিত নয়।

এটি কোড গল্ফ, তাই সংক্ষিপ্ততম জমা (বাইটে) জিতেছে।

অনুমিতি

  • সকল স্থানাঙ্ক সীমার মধ্যে পূর্ণসংখ্যা 0 ≤ x ≤ 100, 0 ≤ y ≤ 100
  • কমপক্ষে 3এবং বেশিরভাগ শীর্ষে থাকবে 50
  • কোনও পুনরাবৃত্তি উল্লম্ব হবে না। উভয় প্রান্তই অন্য প্রান্তে থাকবে না। ( তবে তালিকায় কলিনারি পয়েন্ট থাকতে পারে))

পরীক্ষার মামলা

{{0, 0}, {5, 0}, {5, 4}, {1, 4}, {1, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 1}, {4, 1}, {4, 5}, {0, 5}}
17.0000

{{22, 87}, {6, 3}, {98, 77}, {20, 56}, {96, 52}, {79, 34}, {46, 78}, {52, 73}, {81, 85}, {90, 43}}
2788.39

{{90, 43}, {81, 85}, {52, 73}, {46, 78}, {79, 34}, {96, 52}, {20, 56}, {98, 77}, {6, 3}, {22, 87}}
2788.39

{{70, 33}, {53, 89}, {76, 35}, {14, 56}, {14, 47}, {59, 49}, {12, 32}, {22, 66}, {85, 2}, {2, 81},
 {61, 39}, {1, 49}, {91, 62}, {67, 7}, {19, 55}, {47, 44}, {8, 24}, {46, 18}, {63, 64}, {23, 30}}
2037.98

{{42, 65}, {14, 59}, {97, 10}, {13, 1}, {2, 8}, {88, 80}, {24, 36}, {95, 94}, {18, 9}, {66, 64},
 {91, 5}, {99, 25}, {6, 66}, {48, 55}, {83, 54}, {15, 65}, {10, 60}, {35, 86}, {44, 19}, {48, 43},
 {47, 86}, {29, 5}, {15, 45}, {75, 41}, {9, 9}, {23, 100}, {22, 82}, {34, 21}, {7, 34}, {54, 83}}
3382.46

{{68, 35}, {43, 63}, {66, 98}, {60, 56}, {57, 44}, {90, 52}, {36, 26}, {23, 55}, {66, 1}, {25, 6},
 {84, 65}, {38, 16}, {47, 31}, {44, 90}, {2, 30}, {87, 40}, {19, 51}, {75, 5}, {31, 94}, {85, 56},
 {95, 81}, {79, 80}, {82, 45}, {95, 10}, {27, 15}, {18, 70}, {24, 6}, {12, 73}, {10, 31}, {4, 29},
 {79, 93}, {45, 85}, {12, 10}, {89, 70}, {46, 5}, {56, 67}, {58, 59}, {92, 19}, {83, 49}, {22,77}}
3337.62

{{15, 22}, {71, 65}, {12, 35}, {30, 92}, {12, 92}, {97, 31}, {4, 32}, {39, 43}, {11, 40}, 
 {20, 15}, {71, 100}, {84, 76}, {51, 98}, {35, 94}, {46, 54}, {89, 49}, {28, 35}, {65, 42}, 
 {31, 41}, {48, 34}, {57, 46}, {14, 20}, {45, 28}, {82, 65}, {88, 78}, {55, 30}, {30, 27}, 
 {26, 47}, {51, 93}, {9, 95}, {56, 82}, {86, 56}, {46, 28}, {62, 70}, {98, 10}, {3, 39}, 
 {11, 34}, {17, 64}, {36, 42}, {52, 100}, {38, 11}, {83, 14}, {5, 17}, {72, 70}, {3, 97}, 
 {8, 94}, {64, 60}, {47, 25}, {99, 26}, {99, 69}}
3514.46

1
বিশেষত, আমি সীমান্তকারীদের এমনভাবে প্রতিস্থাপন করতে চাই যা তালিকাকে একটি বৈধ পোস্টস্ক্রিপ্ট ব্যবহারকারী পথ হিসাবে চিহ্নিত করে, যাতে আমি একটি upathঅপারেটর দিয়ে পুরো জিনিসটি পার্স করতে পারি । (এটি প্রকৃতপক্ষে পৃথককারীদের মধ্যে একটি অত্যন্ত সাধারণ 1: 1 রূপান্তর }, {just স্রেফ হয়ে যায় linetoএবং x এবং y এর মধ্যে কমাটি সরিয়ে ফেলা হয়, এবং খোলার এবং
সমাপনকারী বন্ধনীগুলি

1
@ এজেম্যান্সফিল্ডে আমি সাধারণত সুবিধাজনক, নেটিভ তালিকার উপস্থাপনাগুলি ব্যবহার করতে আপত্তি করি না তবে ব্যবহার upathএবং এমন linetoশব্দগুলি মনে হয় যে আপনি প্রকৃতপক্ষে ইনপুটটিকে প্রসেসরোস করছেন। অর্থাৎ আপনি স্থানাঙ্কগুলির একটি তালিকা না নিয়ে একটি আসল বহুভুজ।
মার্টিন ইন্ডার

1
@ ম্যাটনুনন ওহ, এটি একটি ভাল বিষয়। হ্যাঁ আপনি ধরে নিতে পারেন।
মার্টিন ইন্ডার

2
@ রায় যদিও দিকটি ক্রসিংয়ের সংখ্যাকে প্রভাবিত করতে পারে, তবুও এটি প্যারিটি সংরক্ষণ করে কেবল 2 বা কমবে। আমি একটি রেফারেন্স সন্ধান করার চেষ্টা করব। শুরু করার জন্য, এসভিজি একই সংজ্ঞা ব্যবহার করে।
মার্টিন ইন্ডার

1
ম্যাথামেটিকাল 12.0 একটি নতুন হয়েছে বিল্ট-ইন এই জন্য ফাংশন: CrossingPolygon
আলেফাল্ফ

উত্তর:


14

গণিত, 247 225 222

p=Partition[#,2,1,1]&;{a_,b_}~r~{c_,d_}=Det/@{{a-c,c-d},{a,c}-b}/Det@{a-b,c-d};f=Abs@Tr@MapIndexed[Det@#(-1)^Tr@#2&,p[Join@@MapThread[{1-#,#}&/@#.#2&,{Sort/@Cases[{s_,t_}/;0<=s<=1&&0<=t<=1:>s]/@Outer[r,#,#,1],#}]&@p@#]]/2&

প্রথমে বহুভুজের ছেদ বিন্দু যুক্ত করুন, তারপরে কয়েকটি কিনারা বিপরীত করুন, তারপরে এর অঞ্চলটি একটি সাধারণ বহুভুজের মতো গণনা করা যেতে পারে।

এখানে চিত্র বর্ণনা লিখুন

উদাহরণ:

In[2]:= f[{{15, 22}, {71, 65}, {12, 35}, {30, 92}, {12, 92}, {97, 31}, {4, 32}, {39, 43}, {11, 40}, 
 {20, 15}, {71, 100}, {84, 76}, {51, 98}, {35, 94}, {46, 54}, {89, 49}, {28, 35}, {65, 42}, 
 {31, 41}, {48, 34}, {57, 46}, {14, 20}, {45, 28}, {82, 65}, {88, 78}, {55, 30}, {30, 27}, 
 {26, 47}, {51, 93}, {9, 95}, {56, 82}, {86, 56}, {46, 28}, {62, 70}, {98, 10}, {3, 39}, 
 {11, 34}, {17, 64}, {36, 42}, {52, 100}, {38, 11}, {83, 14}, {5, 17}, {72, 70}, {3, 97}, 
 {8, 94}, {64, 60}, {47, 25}, {99, 26}, {99, 69}}]

Out[2]= 3387239559852305316061173112486233884246606945138074528363622677708164\
 6419838924305735780894917246019722157041758816629529815853144003636562\
 9161985438389053702901286180223793349646170997160308182712593965484705\
 3835036745220226127640955614326918918917441670126958689133216326862597\
 0109115619/\
 9638019709367685232385259132839493819254557312303005906194701440047547\
 1858644412915045826470099500628074171987058850811809594585138874868123\
 9385516082170539979030155851141050766098510400285425157652696115518756\
 3100504682294718279622934291498595327654955812053471272558217892957057\
 556160

In[3]:= N[%] (*The numerical value of the last output*)

Out[3]= 3514.46

দুর্ভাগ্যক্রমে আমি নিশ্চিত নই যে এই যুক্তিটি সমস্ত পরিস্থিতিতে কাজ করবে। আপনি চেষ্টা করতে পারেন {1,2},{4,4},{4,2},{2,4},{2,1},{5,3}? আপনার 3.433333333333309 দিয়ে বেরিয়ে আসা উচিত। আমি একটি অনুরূপ যুক্তি ব্যবহার করে তাকিয়ে।
মিকিটি

@ মিকিটি হ্যাঁ, এটি কাজ করে। এটি ফিরে এসেছিল 103/30এবং সংখ্যাসূচক মান 3.43333
আলেফাল্ফ

এর জন্যে দুঃখিত. ভাল সমাধান
মিকিটি

44

পাইথন 2, 323 319 বাইট

exec u"def I(s,a,b=1j):c,d=s;d-=c;c-=a;e=(d*bX;return e*(0<=(b*cX*e<=e*e)and[a+(d*cX*b/e]or[]\nE=lambda p:zip(p,p[1:]+p);S=sorted;P=E(input());print sum((t-b)*(r-l)/2Fl,r@E(S(i.realFa,b@PFe@PFi@I(e,a,b-a)))[:-1]Fb,t@E(S(((i+j)XFe@PFi@I(e,l)Fj@I(e,r)))[::2])".translate({70:u" for ",64:u" in ",88:u".conjugate()).imag"})

নিম্নলিখিত ফর্মটিতে জটিল সংখ্যা হিসাবে STDIN এর মাধ্যমে শীর্ষের তালিকা তৈরি করে T

[  X + Yj,  X + Yj,  ...  ]

, এবং STDOUT এ ফলাফল লিখুন।

স্ট্রিং প্রতিস্থাপন এবং কিছু ব্যবধানের পরে একই কোড:

def I(s, a, b = 1j):
    c, d = s; d -= c; c -= a;
    e = (d*b.conjugate()).imag;
    return e * (0 <= (b*c.conjugate()).imag * e <= e*e) and \
           [a + (d*c.conjugate()).imag * b/e] or []

E = lambda p: zip(p, p[1:] + p);
S = sorted;

P = E(input());

print sum(
    (t - b) * (r - l) / 2

    for l, r in E(S(
        i.real for a, b in P for e in P for i in I(e, a, b - a)
    ))[:-1]

    for b, t in E(S(
        ((i + j).conjugate()).imag for e in P for i in I(e, l) for j in I(e, r)
    ))[::2]
)

ব্যাখ্যা

ইনপুট বহুভুজ উভয় পক্ষের ছেদ করার প্রতিটি বিন্দুর জন্য (শীর্ষগুলি সহ), বিন্দু হলেও একটি উল্লম্ব রেখাটি পাস করুন।

চিত্র 1

(প্রকৃতপক্ষে, গল্ফিংয়ের কারণে, প্রোগ্রামটি আরও কয়েকটি লাইন পেরিয়ে যায়; যতক্ষণ না আমরা কমপক্ষে এই লাইনগুলি পাস করি ততক্ষণ তা সত্যিকার অর্থে কোনও ব্যাপার নয়)) পর পর দুটি দুটি লাইনের মধ্যবর্তী বহুভুজের দেহটি উল্লম্ব ট্র্যাপিজয়েড নিয়ে গঠিত ( এবং ত্রিভুজ এবং রেখাংশগুলি, এর বিশেষ ক্ষেত্রে হিসাবে)। এটি ক্ষেত্রে হতে হবে, যেহেতু যদি এই আকারগুলির কোনওরই দুটি ঘাঁটির মধ্যে একটি অতিরিক্ত শীর্ষবিন্দু থাকে, তবে সেই বিন্দুর মধ্য দিয়ে আরও দুটি উল্লম্ব রেখা থাকবে, প্রশ্নযুক্ত দুটি লাইনের মধ্যে। এই জাতীয় সমস্ত ট্র্যাপিজয়েডগুলির ক্ষেত্রগুলির যোগফলটি বহুভুজের ক্ষেত্রফল।

এই ট্র্যাপিজয়েডগুলি কীভাবে আমরা খুঁজে পাই তা এখানে: একটানা উল্লম্ব লাইনগুলির প্রতিটি জোড়া জন্য, আমরা বহুভুজের প্রতিটি পাশের অংশগুলি খুঁজে পাই যা (সঠিকভাবে) এই দুটি লাইনের (যা কিছু পক্ষের জন্য অস্তিত্ব থাকতে পারে) এর মধ্যে রয়েছে। উপরের চিত্রটিতে, দুটি লাল উলম্ব রেখা বিবেচনা করার সময় এগুলি ছয়টি লাল অংশ gments মনে রাখবেন যে এই বিভাগগুলি একে অপরকে যথাযথভাবে ছেদ করে না (যেমন, তারা কেবল তাদের শেষ পয়েন্টগুলিতে মিলিত হতে পারে, পুরোপুরি একত্রিত হয় বা একেবারে ছেদ করতে পারে না, যেহেতু, যদি তারা আবার যথাযথভাবে ছেদ করে তবে এর মধ্যে অন্য একটি উল্লম্ব রেখা থাকবে;) এবং তাই তাদের শীর্ষে থেকে নীচে অর্ডার দেওয়ার বিষয়ে কথা বলার অর্থ হয়, যা আমরা করি। অদ্ভুত নিয়ম অনুসারে, একবার আমরা প্রথম বিভাগটি অতিক্রম করার পরে, আমরা বহুভুজের ভিতরে থাকি; একবার আমরা দ্বিতীয়টি পেরিয়ে গেলে, আমরা বাইরে চলে যাই; তৃতীয়টি আবার; চতুর্থ, আউট; এবং তাই ...

সামগ্রিকভাবে, এটি একটি ( এন 3 লগ এন ) অ্যালগরিদম।


4
ইহা অসাধারণ! আমি জানতাম আমি এর জন্য আপনার উপর নির্ভর করতে পারি। ;) (আপনি স্ট্যাক ওভারফ্লোতে এই প্রশ্নের উত্তর দিতে চাইতে পারেন ))
মার্টিন এন্ডার

@ মার্টিনব্যাটনার তাদের আসতে আসুন :)
এল

7
দুর্দান্ত কাজ এবং দুর্দান্ত ব্যাখ্যা
মিকটি

1
এটি একটি চিত্তাকর্ষক উত্তর। আপনি নিজেই অ্যালগরিদম বিকাশ করেছেন বা এই সমস্যা নিয়ে কোনও বিদ্যমান কাজ রয়েছে? যদি বিদ্যমান কাজ থাকে তবে আমি যেখানে এটি সন্ধান করতে পারি তার একটি পয়েন্টারের প্রশংসা করব। এটি কীভাবে মোকাবেলা করা যায় সে সম্পর্কে আমার কোনও ধারণা ছিল না।
লজিক নাইট

5
@ কার্পেট পাইথন আমি এটি নিজেই বিকাশ করেছি, তবে এটি যদি আগে না করা হয় তবে আমি খুব অবাক হব।
ইল

9

হাস্কেল, 549

দেখে মনে হচ্ছে না যে আমি এটিকে যথেষ্ট পরিমাণে গল্ফ করতে পারি, তবে ধারণাটি অন্য দুটি উত্তরের চেয়ে আলাদা ছিল তাই আমি বুঝতে পেরেছিলাম যে আমি এটি ভাগ করে নিই। এটি অঞ্চলটি গণনা করার জন্য ও (এন ^ 2) যৌক্তিক ক্রিয়াকলাপ সম্পাদন করে।

import Data.List
_%0=2;x%y=x/y
h=sort
z f w@(x:y)=zipWith f(y++[x])w
a=(%2).sum.z(#);(a,b)#(c,d)=b*c-a*d
(r,p)?(s,q)=[(0,p)|p==q]++[(t,v t p r)|u t,u$f r]where f x=(d q p#x)%(r#s);t=f s;u x=x^2<x
v t(x,y)(a,b)=(x+t*a,y+t*b);d=v(-1)
s x=zip(z d x)x
i y=h.(=<<y).(?)=<<y
[]!x=[x];x!_=x
e n(a@(x,p):y)|x>0=(n!y,a):(e(n!y)$tail$dropWhile((/=p).snd)y)|0<1=(n,a):e n y
c[p]k=w x[]where((_,q):x)=e[]p;w((n,y):z)b|q==y=(k,map snd(q:b)):c n(-k)|0<1=w z(y:b);c[]_=[]
b(s,p)=s*a p
u(_,x)(_,y)=h x==h y
f p=abs$sum$map b$nubBy u$take(length p^2)$c[cycle$i$s p]1

উদাহরণ:

λ> f test''
33872395598523053160611731124862338842466069451380745283636226777081646419838924305735780894917246019722157041758816629529815853144003636562916198543838905370290128618022379334964617099716030818271259396548470538350367452202261276409556143269189189174416701269586891332163268625970109115619 % 9638019709367685232385259132839493819254557312303005906194701440047547185864441291504582647009950062807417198705885081180959458513887486812393855160821705399790301558511410507660985104002854251576526961155187563100504682294718279622934291498595327654955812053471272558217892957057556160
λ> fromRational (f test'')
3514.4559380388832

বহু ক্রসিংয়ে বহুভুজটি পুনর্নির্মাণ করার ধারণাটি হ'ল ফলস্বরূপ প্রান্তগুলি ছাড়াই বহুভুজগুলির মিলন। এরপরে আমরা গৌসের জুতার সূত্র ( http://en.wikedia.org/wiki/Shoelace_formula ) ব্যবহার করে প্রতিটি বহুভুজগুলির (স্বাক্ষরিত) ক্ষেত্রটি গণনা করতে পারি । অদ্ভুত নিয়মটি দাবি করে যে যখন একটি ক্রসিং রূপান্তরিত হয় তখন নতুন বহুভুজের ক্ষেত্রটি পুরানো বহুভুজের তুলনায় নেতিবাচকভাবে গণনা করা হয়।

উদাহরণস্বরূপ, মূল প্রশ্নের বহুভুজটি বিবেচনা করুন। উপরের-বামে ক্রসিং দুটি পথে রূপান্তরিত হয়েছে যা কেবলমাত্র একটি বিন্দুতে মিলিত হয়; দুটি পাথ উভয়ই ঘড়ির কাঁটামুখী, সুতরাং প্রতিটিটির ক্ষেত্রগুলি ইতিবাচক হবে যদি না আমরা ঘোষণা না করি যে অভ্যন্তরীণ পথটি বাইরের পথের তুলনায় -1 দ্বারা ওজনিত হয়। এটি আলফালফার পথের বিপরীতে সমান।

বহুভুজ আসল উদাহরণ থেকে প্রাপ্ত

অন্য উদাহরণ হিসাবে, মিকিটির মন্তব্য থেকে বহুভুজটি বিবেচনা করুন:

বহুবিদরা মিকিটির মন্তব্য থেকে প্রাপ্ত

এখানে, বহুভুজগুলির কয়েকটি ঘড়ির কাঁটার দিকে এবং কিছুটি ঘড়ির কাঁটার দিকে। সাইন-ফ্লিপ-অন-ক্রসিং নিয়মটি নিশ্চিত করে যে ঘড়ির কাঁটা-ভিত্তিক অঞ্চলগুলি -1 এর একটি অতিরিক্ত ফ্যাক্টর গ্রহণ করবে, যার ফলে তারা এই অঞ্চলে ইতিবাচক পরিমাণে অবদান রাখবে।

প্রোগ্রামটি কীভাবে কাজ করে তা এখানে:

import Data.List  -- for sort and nubBy

-- Rational division, with the unusual convention that x/0 = 2
_%0=2;x%y=x/y

-- Golf
h=sort

-- Define a "cyclic zipWith" operation. Given a list [a,b,c,...z] and a binary
-- operation (@), z (@) [a,b,c,..z] computes the list [b@a, c@b, ..., z@y, a@z]
z f w@(x:y)=zipWith f(y++[x])w

-- The shoelace formula for the signed area of a polygon
a=(%2).sum.z(#)

-- The "cross-product" of two 2d vectors, resulting in a scalar.
(a,b)#(c,d)=b*c-a*d

-- Determine if the line segment from p to p+r intersects the segment from
-- q to q+s.  Evaluates to the singleton list [(t,x)] where p + tr = x is the
-- point of intersection, or the empty list if there is no intersection. 
(r,p)?(s,q)=[(0,p)|p==q]++[(t,v t p r)|u t,u$f r]where f x=(d q p#x)%(r#s);t=f s;u x=x^2<x

-- v computes an affine combination of two vectors; d computes the difference
-- of two vectors.
v t(x,y)(a,b)=(x+t*a,y+t*b);d=v(-1)

-- If x is a list of points describing a polygon, s x will be the list of
-- (displacement, point) pairs describing the edges.
s x=zip(z d x)x

-- Given a list of (displacement, point) pairs describing a polygon's edges,
-- create a new polygon which also has a vertex at every point of intersection.
-- Mercilessly golfed.
i y=h.(=<<y).(?)=<<y


-- Extract a simple polygon; when an intersection point is reached, fast-forward
-- through the polygon until we return to the same point, then continue.  This
-- implements the edge rewiring operation. Also keep track of the first
-- intersection point we saw, so that we can process that polygon next and with
-- opposite sign.
[]!x=[x];x!_=x
e n(a@(x,p):y)|x>0=(n!y,a):(e(n!y)$tail$dropWhile((/=p).snd)y)|0<1=(n,a):e n y

-- Traverse the polygon from some arbitrary starting point, using e to extract
-- simple polygons marked with +/-1 weights.
c[p]k=w x[]where((_,q):x)=e[]p;w((n,y):z)b|q==y=(k,map snd(q:b)):c n(-k)|0<1=w z(y:b);c[]_=[]

-- If the original polygon had N vertices, there could (very conservatively)
-- be up to N^2 points of intersection.  So extract N^2 polygons using c,
-- throwing away duplicates, and add up the weighted areas of each polygon.
b(s,p)=s*a p
u(_,x)(_,y)=h x==h y
f p=abs$sum$map b$nubBy u$take(length p^2)$c[cycle$i$s p]1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.