সংসদীয় আসন বিতরণ করা হচ্ছে


13

ভূমিকা

একটি সাধারণ নির্বাচনে, সংসদীয় আসন প্রতি স্থির মূল্য গণনা করতে চাই। এর অর্থ এই যে জন্য N >= 0আসন বণ্টন করা প্রয়োজন এবং একটি তালিকা nsপার্টি অনুযায়ী ভোট, আমরা একটি সংখ্যা খুঁজে বের করতে চাই dযেমন যে

sum(floor(n/d) for n in ns) == N 

জিনিসগুলিকে আকর্ষণীয় করে তুলতে (এবং আরও বাস্তব বিশ্বের মতো), আমরা আরও দুটি তথ্য যুক্ত করি:

  1. দুটি দল একটি 'জোটে' জড়ো হতে পারে, যাতে আসনগুলিতে সমস্ত দলের ভোটের যোগফল দ্বারা 'জোটকে' দেওয়া হয়। তারপরে 'জোট' প্রাপ্ত আসনগুলি একই ধরণের দলগুলির মধ্যে বিভক্ত হয়ে যাবে (বিভাজন অনুসন্ধান করুন ইত্যাদি))

  2. যে দলটি ভোটের একটি নির্দিষ্ট শতাংশ (উদাহরণস্বরূপ 3.25%) পাস করেনি তা স্বয়ংক্রিয়ভাবে 0 টি আসন লাভ করে এবং এর ভোটগুলি 'জোট' হিসাবে গণ্য হয় না।

চ্যালেঞ্জ

আপনাকে দেওয়া হল:

  1. তালিকাভুক্ত তালিকার প্রতিটি নেস্টেড তালিকায় পূর্ণসংখ্যার (ভোটের সংখ্যা) রয়েছে এবং এটি একটি একক দলের জন্য দৈর্ঘ্য 1 এবং একটি 'জোটের' জন্য দৈর্ঘ্য 2।
  2. ভগ্নাংশ হিসাবে আসন পেতে ন্যূনতম শতাংশের ভোট ("ব্যারেজের জন্য" ওরফে "বার") (সুতরাং ৩.২৫% 0.0325 হিসাবে দেওয়া হয়)
  3. সমস্ত দলের (পূর্ণসংখ্যার) মধ্যে বিতরণ করার জন্য মোট আসন সংখ্যা

আপনি সংসদীয় আসনের পরিবর্তে ভোটের সংখ্যা সহ একই নেস্টেড তালিকা কাঠামোটি মুদ্রণ করতে হবে।

বিজয়ী হ'ল সর্বনিম্ন পরিমাণে বাইট সহ কোড।

কোণার কেস:

  • একাধিক সম্ভাব্য বিভাজক (এবং সাধারণত হতে পারে) থাকতে পারে। যেহেতু এটি আউটপুটে নেই, তাই এটি আসলে কোনও বিষয় নয়।
  • কল্পনা করুন N=10এবং ns = [[1]], তাই বিভাজকটি 0.1 হতে পারে (কোনও পূর্ণসংখ্যার নয়)
  • কিছু কিছু ক্ষেত্রে উদাহরণস্বরূপ সমাধান করা যায় না, , ns=[[30],[30],[100]], ।bar=0 N=20সেখানে একটি সীমানা রয়েছে d=7.5যেখানে মেঝেযুক্ত মানগুলির যোগফল 19 থেকে 21 পর্যন্ত লাফায় You (এই কেসটি দেখানোর জন্য কমিউনিটির সদস্য আর্নল্ডকে ধন্যবাদ)

উদাহরণ ইনপুট এবং আউটপুট

পাইথন 3 একটি খুব অপ্টিমাইজড উদাহরণ:

from math import floor

def main(_l, bar, N):
    # sum all votes to calculate bar in votes
    votes = sum(sum(_) for _ in _l)

    # nullify all parties that didn't pass the bar
    _l = [[__ if __ >= bar * votes else 0 for __ in _] for _ in _l]

    # find divisor for all parliament seats
    divisor = find_divisor([sum(_) for _ in _l], N)

    # find divisor for each 'coalition'
    divisors = [find_divisor(_, floor(sum(_)/divisor)) for _ in _l]

    # return final results
    return [[floor(___/_) for ___ in __] for _, __ in zip(divisors, _l)]

def find_divisor(_l, N, _min=0, _max=1):
    s = sum(floor(_ / _max) for _ in _l)
    if s == N:
            return _max
    elif s < N:
            return find_divisor(_l, N, _min, (_max + _min) / 2)
    else:
            return find_divisor(_l, N, _max, _max * 2)

print(main(l, bar, N))

উদাহরণ ইনপুট:

l = [[190970, 156473], 
    [138598, 173004], 
    [143666, 193442], 
    [1140370, 159468], 
    [258275, 249049], 
    [624, 819], 
    [1125881], 
    [152756], 
    [118031], 
    [74701]]
bar = 0.0325
N = 120

এবং এর আউটপুট:

[[6, 4], [0, 5], [4, 6], [35, 5], [8, 8], [0, 0], [35], [4], [0], [0]]

আরও কিছু উদাহরণ আউটপুট:

যদি bar=0.1আমরা দুটি দলের মধ্যে একটি আকর্ষণীয় স্ট্যান্ড অফ পেয়ে থাকি কারণ ছোট দলের কোনওটিতেই গণ্য হয় না:

[[0, 0], [0, 0], [0, 0], [60, 0], [0, 0], [0, 0], [60], [0], [0], [0]]

এবং যদি N=0(কর্নার কেস) হয় তবে অবশ্যই কেউ কিছু পান না:

[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0], [0], [0], [0]]

5
পিপিসিজিতে আপনাকে স্বাগতম!
আর্নল্ড

সিজিসিসিতে স্বাগতম (পূর্বে পিপিসিজি হিসাবে পরিচিত)! পাইথন হাইলাইট করার জন্য আমি আপনার স্বাধীনতা যোগ করেছি যাতে আপনার কোডটি আরও পঠনযোগ্য হয়ে যায় এবং আমি কোডের নীচে ইনপুটটি রেখে দিয়েছি যাতে ইনপুট-আউটপুট একসাথে আরও ঘনিষ্ঠ হয়। আমি দুটি প্রাসঙ্গিক ট্যাগ যুক্ত করেছি। ভাল প্রথম চ্যালেঞ্জ, সুতরাং আমার কাছ থেকে +1! পিএস: আপনি প্রস্তাবিত চ্যালেঞ্জগুলির স্যান্ডবক্স ব্যবহার করতে পারেন চ্যালেঞ্জগুলিকে মূল পোস্ট করার আগে তাদের প্রতিক্রিয়া জানাতে, যদিও এই ক্ষেত্রে আমি মনে করি চ্যালেঞ্জটি পরিষ্কার। সম্ভবত কয়েকটি অতিরিক্ত পরীক্ষার কেস যুক্ত করবেন? আপনার থাকার উপভোগ করুন :)
কেভিন ক্রুইজসেন

নিশ্চিত কথাটি কেভিন ক্রুজসেন, আমি আরও দুটি মামলা যুক্ত করেছি। বিদ্যমান আউটপুট হিসাবে আমি এটি সত্য বলে বিশ্বাস করি এটি একটি সাম্প্রতিক নির্বাচনের সঠিক ফলাফল :)
স্কেফ

@ আর্নল্ড কৌতূহলের বাইরে, সেই পরীক্ষার ক্ষেত্রে প্রত্যাশিত আউটপুটটি কী হওয়া উচিত?
কেভিন ক্রুইজসেন

1
আমি ইতিমধ্যে কোণার ক্ষেত্রে একটি বুলেট যুক্ত করেছি, আমি মনে করি যে এটি সীমানা হিসাবে আপনি d=7.519 টি আসন থেকে 21 টি আসনে লাফিয়ে উঠতে পারেন না is
scf

উত্তর:


2

05 এ বি 1 ই , 42 39 বাইট

ÐOOI*@*DO¸I¸¸2Fнζε`sDO/*Щ±/D{®1%Oòè‹+ï

এটি অনলাইন চেষ্টা করুন!

05AB1E ভাল পুনরাবৃত্তি অভাব, সুতরাং রেফারেন্স কোড হিসাবে একটি বাইনারি অনুসন্ধান বাস্তবায়ন বেদনাদায়ক হবে। ধন্যবাদ, আমাদের মোটেই বিভাজকের সন্ধান করার দরকার নেই!

আসুন একটি সহজ উদাহরণ ব্যবহার করুন: [600, 379, 12, 9] ভোট, 100 টি আসন, কোনও জোট নয়, কোনও বার নেই। প্রথমত, আমরা প্রতিটি দল কতটি ভগ্নাংশ আসন লাভ করি তা গণনা করি , ভগ্নাংশের আসন হিসাবে সংজ্ঞা প্রদান করি party_votes * seats / sum_of_votes। আমাদের উদাহরণে, এটি [60, 37.9, 1.2, 0.9] দেয়।

আকর্ষণীয় বিট যে যদি একটি দল পায় fভগ্ন আসন, এটা হয় পাবেন int(f)বা int(f) + 1বাস্তব টি আসন। এর অর্থ আমরা ইতিমধ্যে জানি যে কীভাবে 60 + 37 + 1 = 98 আসন বরাদ্দ হবে এবং 4 টি দলের মধ্যে বিতরণ করার জন্য আমাদের 2 টি "বোনাস আসন" বাকি রয়েছে (কোনও দল 1 বোনাসের বেশি আসন পেতে পারে না)। এই বোনাস আসন কারা যায়? সর্বাধিক অনুপাত সহ পক্ষগুলি f / (int(f) + 1)(পাঠকের কাছে অনুশীলন হিসাবে প্রমাণ রেখে গেছে)। আমাদের উদাহরণগুলিতে, অনুপাতগুলি হ'ল [0.98, 0.997, 0.6, 0.9], সুতরাং প্রথম দুটি দল প্রতিটি করে বোনাস আসন পায়।


কোডটি একবার দেখুন। প্রথমত, আমরা সমস্ত দলের পক্ষে ভোট গণনা প্রতিস্থাপন করি যা 0:

Ð          # triplicate the first input (list of votes)
 OO        # flattened sum
   I*      # multiply by the second input (bar)
     @     # greater than? (returns 0 or 1)
      *    # multiply

এখন, 2Fপুনরাবৃত্তি ঘাটতি ঘাটতি কাজ করার জন্য , আমরা মূল কোডটি দু'বার পুনরাবৃত্তি করতে একটি অকার্ড ব্যবহার করি । প্রথম পাসে এটি জোটের মধ্যে মোট আসন বিতরণ করবে এবং দ্বিতীয় পাসে এটি প্রতিটি জোটের আসনগুলিকে তার দলের মধ্যে বিতরণ করবে। যেহেতু প্রথম পাসটি কেবল একবার চালানো হয়, তবে দ্বিতীয় পাসটি প্রতিটি জোটের হয়ে চলে, এতে ব্যস্ততার চেয়ে অনেক বেশি কাজ জড়িত।

DO¸I¸¸2Fнζε`s    # i don’t want to detail this tbh

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

D        # duplicate
 O       # sum  
  /      # divide each vote count by the sum
   *     # multiply by the number of seats
    ©    # save the fractional seats in variable r

এখন, আমরা অনুপাত গণনা:

Ð            # triplicate
 ±           # bitwise not
  /          # divide

কিন্তু এখানে সুন্দরভাবে কাজ করে না। এটি পূর্ণসংখ্যার সাথে সংক্ষিপ্ত আকারে 1 টি যোগ করে এবং সমস্তগুলি একক বাইটে উপেক্ষা করে। কেন অবহেলা করবেন? 05AB1E তে 0 দ্বারা বিভাজন 0 প্রদান করে এবং আমাদের শেষের অনুসারে বাছাই করা দরকার।

ডি {# অনুপাতের সাজানো অনুলিপি votes১% # ভগ্নাংশ ভোট মোড 1 (ওরফ দশমিক অংশ) ও # উপরের যোগফল (এটি বোনাস আসনের সংখ্যা) nearest # নিকটতম (ভাসমান পয়েন্ট বি এর কারণে প্রয়োজনীয়) s # অনুসারে বাছাই করা অনুপাতের সূচক

এটি আমাদেরকে (n + 1) তম সেরা অনুপাত দেয়, যেখানে এন হল বোনাস আসনের সংখ্যা (+1 কারণ সূচক 0 ভিত্তিক)। সুতরাং, যে দলগুলি বোনাস আসন পায় তারা হ'ল এই অনুপাতের চেয়ে কম অনুপাত রয়েছে।

‹      # less than
 +     # add to the fractional seats
  ï    # truncate to integer

খুব সুন্দর. আপনার কোডটি অপ্টিমাইজ করার জন্য গণিত ব্যবহারের দুর্দান্ত উপায় :)
স্কেফ


1

জেলি , 63 36 বাইট

F×S<ḷ×ḷµ§⁵:,1_×¥:@"§IṠʋ÷9ɗ¥ƬṪṪƲ¥¥@⁺"

এটি অনলাইন চেষ্টা করুন!

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

ব্যাখ্যা

F×S<ḷ×ḷµ§⁵:,1_×¥:@"§IṠʋ÷9ɗ¥ƬṪṪƲ¥¥@⁺"

F                                   | Flatten vote counts
 ×                                  | Multiply by bar
  S                                 | Sum
   <ḷ                               | Less than original vote counts (vectorises and respects input list structure)
     ×ḷ                             | Multiply by original vote counts
       µ                            | Start a new monadic link with processed vote counts as input
        §                           | Vectorised sum

         ⁵                      ¥@  | Apply the following as a dyad with the number of seats as the right argument and the vectorised sum of votes as left

           ,                  Ʋ¥    |(*)- Pair vote counts with seat sum and find divisor using the following as a monad:
            1             ¥Ƭ        |     - Starting with 1 as a guess for divisor, and using the paired vote counts and seat sum as the right argument, apply the following as a dyad, collecting intermediate results, until the results repeat
                         ɗ          |       - Following as a dyad:
                      ʋ             |         - Following as a dyad:
                :@"                 |           - Integer divide with arguments zipped and reversed, i.e. divide cote counts by current divisor guess and leave total seats alone
                   §                |           -  Vectorised sum (will sum vote counts but leave seat number alone)
                    I               |           - Find differences i.e. desired total seats minus current calculation based on current divisor guess. Will return a list.
                     Ṡ              |           - Sign of this (-1, 0 or 1)
                       ÷9           |         - Divide by 9 (-0.111, 0 or 0.111)
             _×¥                    |     - Now multiply the current divisor guess by this and subtract it from that guess to generate the next guess. If the current guess is correct, the guess will be unchanged and so the Ƭ loop will terminate
                            ṪṪ      |     - Take the last item twice (first time to get the final
                               output of the Ƭ loop and second to remove the list introduced by I
         :                          | - Integer divide the vote counts by the output of the above

                                  ⁺"| Apply the above dyad from the step labelled (*) again, this time with the output of the previous step (total votes per coalition) as right argument and the vote counts as left argument, zipping the two together and running the link once for each pair

আসল জমা (বৃহত্তর তবে আরও দক্ষ)

জেলি , 63 বাইট

:S_3ƭƒṠ©ḢḤ;$;ṪƲṖÆm;ḊƲ®‘¤?ߥ/}ṛ¹?,
1,0;çḢḢ
FS×Ċ’<ḷ×ḷµ:"§:⁵ç$$ç"Ɗ

এটি অনলাইন চেষ্টা করুন!


ভাল জমা। আমি এটি ইনপুট [[1]] 0.0 10 দিয়ে চেষ্টা করেছিলাম, যা আমি প্রত্যাশা করি [[10]] (কোণার ক্ষেত্রে বুলেট পয়েন্ট 2 দেখুন) এবং সময় শেষ হয়ে গেল। আপনি এটি নিশ্চিত করতে পারেন যে এটি অত্যন্ত দীর্ঘ সময় এবং কোনও বাগ নয়?
scf

আসল জমাটি সেই ইনপুট বিটিডব্লিউয়ের সাথে কাজ করে।
scf

@scf আমি ভুলভাবে ধরে নিয়েছিলাম ভোটগুলি আসনগুলির চেয়ে সর্বদা বেশি ছিল। সংশোধিত সংস্করণ ঠিক আছে (এবং আরও কার্যকর) কাজ করা উচিত।
নিক কেনেডি

1
খুব ভাল লাগছে! আপনি কোডটি কিছুটা ব্যাখ্যা করতে পারলে ভালো লাগবে।
scf

নাইভ প্রশ্ন: সিলিং কেন গুরুত্বপূর্ণ? যদি আমি সঠিকভাবে বুঝতে পারি আপনি সর্বনিম্ন ভোটের উপর সিলিং সম্পাদন করেন তবে তুলনার জন্য এটি অপ্রয়োজনীয়।
scf

1

ওল্ফ্রাম - কোন গল্ফ

গল্ফিং প্রার্থী নয়, লিনিয়ারপ্রগ্রামিং ব্যবহার করে এটি সমাধান করার জন্য কেবল কৌতূহলী ছিলেন , তবে সম্ভবত কোনও সমস্যার আকর্ষণীয় উপায়:

findDivisor[l_, n_] := Quiet@Module[{s, c, r, m, b, cons, sol},
   s = Length[l];
   c = Append[ConstantArray[0, s], 1];
   r = Thread[Append[IdentityMatrix[s], -l]];
   m = Append[Join[r, r], Append[ConstantArray[1, s], 0]];
   b = Append[Join[ConstantArray[{0, -1}, s], ConstantArray[{-1, 1}, s]], {n, 0}];
   cons = Append[ConstantArray[Integers, s], Reals];
   sol = LinearProgramming[c, m, b, 0, cons];
   {1/sol[[-1]], Most@sol}
   ]
solve[l_, bar_, n_] := 
 With[{t = l /. x_ /; x <= bar Total[l, 2] -> 0},
  With[{sol = findDivisor[Total /@ t, n]}, 
   {First@sol, MapThread[findDivisor, {t, Last@sol}]}]
  ]

কিছু ব্যাখ্যা পড়ুন এবং এটি ব্যবহার করে দেখুন!


যদিও এটি কোনও প্রতিযোগী নয়, পদ্ধতি ও কোড সম্পর্কে কিছু ব্যাখ্যা থাকা শিক্ষামূলক উদ্দেশ্যে দুর্দান্ত হবে।
scf

@scf আমি এটির ব্যাখ্যা করার জন্য আমার প্রচেষ্টার একটি লিঙ্ক যুক্ত করেছি
সুইশ করুন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.