দিনের র্যান্ডম গল্ফ # 3: পূর্ণসংখ্যা পার্টিশন


19

সিরিজ সম্পর্কে

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

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

হোল 3: পূর্ণাঙ্গ পার্টিশন

কিছুটা অসুবিধা বাড়ানোর সময়।

ধনাত্মক পূর্ণসংখ্যার একটি পার্টিশনকে ধনাত্মক পূর্ণসংখ্যার nএকটি মাল্টিসেট হিসাবে সংজ্ঞায়িত করা হয় যা সমষ্টি n। উদাহরণস্বরূপ যদি n = 5, নিম্নলিখিত পার্টিশন উপস্থিত রয়েছে:

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

নোট করুন যে এগুলি মাল্টিস্টেট, সুতরাং তাদের কোনও আদেশ নেই {3,1,1}, {1,3,1}এবং {1,1,3}সমস্তই অভিন্ন বলে বিবেচিত হয়।

আপনার টাস্কটি nএকটি এলোমেলো পার্টিশন তৈরি করার জন্য দেওয়া হয়েছে n। এখানে বিস্তারিত নিয়ম রয়েছে:

  • উত্পাদিত পার্টিশনের বিতরণ অবশ্যই অভিন্ন হতে হবে । এটি, উপরের উদাহরণে, প্রতিটি পার্টিশনটি সম্ভাব্যতা 1/7 দিয়ে ফিরে আসা উচিত।

    অবশ্যই, পিআরএনজিগুলির প্রযুক্তিগত সীমাবদ্ধতার কারণে নিখুঁত অভিন্নতা অসম্ভব হবে। আপনার জমা দেওয়ার অভিন্নতা মূল্যায়নের লক্ষ্যে, নিম্নলিখিত ক্রিয়াকলাপগুলি পুরোপুরি অভিন্ন বিতরণ ফলন হিসাবে বিবেচিত হবে:

    • পিআরএনজি (যে কোনও পরিসীমা ছাড়াই) থেকে একটি সংখ্যা পাওয়া, যা (প্রায়) ইউনিফর্ম হিসাবে নথিভুক্ত।
    • মডুলো বা গুণন (বা অন্য কোনও ক্রিয়াকলাপ যা মানকে সমানভাবে বিতরণ করে) এর মাধ্যমে একটি ছোট সংখ্যায় বৃহত্তর সংখ্যার উপরে অভিন্ন বিতরণ ম্যাপিং। বৃহত্তর সেটটিতে ছোট সেট হিসাবে কমপক্ষে 1024 গুণ যতগুলি সম্ভব মান থাকতে হবে।
  • পার্টিশনগুলি মাল্টিস্টেট হওয়ায় আপনি এগুলি যে কোনও ক্রমে ফিরিয়ে দিতে পারেন এবং এই ক্রমটি সামঞ্জস্যপূর্ণ হতে হবে না। যাইহোক, এলোমেলো বিতরণের উদ্দেশ্যে, আদেশটিকে উপেক্ষা করা হয়। অর্থাৎ উপরের উদাহরণে, {3,1,1}, {1,3,1}এবং {1,1,3} একসঙ্গে ফিরে হচ্ছে 1/7 একটি সম্ভাব্যতা থাকতে হবে।

  • আপনার অ্যালগরিদমের অবশ্যই একটি নির্ধারক রানটাইম থাকতে হবে। বিশেষত, আপনি এলোমেলো মাল্টিসেটগুলি তৈরি করতে এবং সেগুলিকে সম্মতি না দিলে তা প্রত্যাখ্যান করতে পারবেন না n
  • আপনার অ্যালগরিদমের সময়ের জটিলতা অবশ্যই বহুপদী হতে হবে n। বিশেষত, আপনি সহজেই সমস্ত পার্টিশন তৈরি করতে পারবেন না এবং এলোমেলো একটি নির্বাচন করতে পারবেন না (যেহেতু পার্টিশনের সংখ্যা তত দ্রুত বৃদ্ধি পায় n)। আপনি ধরে নিতে পারেন যে আপনি যে পিআরএনজি ব্যবহার করছেন তা প্রতি মূল্য ও (1) এ সমানভাবে বিতরণকৃত মানগুলি ফিরিয়ে দিতে পারে।
  • আপনার অবশ্যই কোনও বিল্ট-ইন ফাংশন ব্যবহার করবেন না যা এই কাজটি সমাধান করে।

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

আপনি ধরে নিতে পারেন n ≤ 65(যেমন পার্টিশনের সংখ্যা ২ 21 এরও কম )। আউটপুট কোনও সুবিধাজনক, দ্ব্যর্থহীন তালিকা বা স্ট্রিং বিন্যাসে থাকতে পারে।

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

এটি কোড গল্ফ, তাই সংক্ষিপ্ততম জমা (বাইটে) জিতেছে। এবং অবশ্যই, ব্যবহারকারী প্রতি সংক্ষিপ্ততম জমাটিও সিরিজের সামগ্রিক লিডারবোর্ডে প্রবেশ করবে।

লিডারবোর্ড

সিরিজের প্রথম পোস্টটি লিডারবোর্ড উত্পন্ন করে।

আপনার উত্তরগুলি প্রদর্শিত হবে তা নিশ্চিত করার জন্য, দয়া করে নীচের মার্কডাউন টেমপ্লেটটি ব্যবহার করে প্রতিটি উত্তর শিরোনাম দিয়ে শুরু করুন:

# Language Name, N bytes

Nআপনার জমা দেওয়ার আকারটি কোথায় ? আপনি যদি নিজের স্কোরটি উন্নত করেন তবে আপনি পুরানো স্কোরগুলি শিরোনামে রেখে দিতে পারেন । এই ক্ষেত্রে:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(ভাষাটি বর্তমানে দেখানো হয়নি, তবে স্নিপেটের প্রয়োজন এবং এটি বিশ্লেষণ করতে পারে এবং ভবিষ্যতে আমি একটি উপ-ভাষা লিডারবোর্ড যুক্ত করতে পারি))

উত্তর:


8

পাইথন 2, 179 বাইট

from random import*
m=r=input();i=q=r+1;h=[1]+[0]*q*q;exec"h[i]=h[i+~q]+h[i-i%q*q];i+=1;"*r*q
while r:
 x=random()*sum(h[r*q:r*q-~m]);m=0
 while x>0:m+=1;x-=h[r*q+m]
 print m;r-=m

আমি এই ন্যুথ এক্সট্র্যাক্ট থেকে সূত্র (39) ব্যবহার করেছি , যা এর অংশগুলির সংখ্যা দেয় যা nঠিক mঅংশে থাকে। এটি এর পার্টিশন সংখ্যা সমান ঘটবে nআছে mসর্বাধিক উপাদান, যা ব্যাখ্যা আমি ব্যবহার করছি হিসাবে। পার্টিশনের উপাদানগুলি বৃহত্তর থেকে কমপক্ষে তৈরি করা হয়। প্রতিটি পর্যায়ে সূত্রটি বর্তমানের অবশিষ্ট nএবং সর্বোচ্চ অনুমোদিত উপাদানগুলির সাথে পুনরায় ব্যবহৃত হয় used


5

ডায়ালগ এপিএল, 67 59 51 বাইট

p←{⍵,⊂1,⍨+/¨⌽⍵↑¨⍨⌽⍳⍴⍵}⍣⎕⊢⍬⋄f←{⍵=0:⍬⋄a,a∇⍵-a←{1++/(?+/⍵)>+\⍵}⍺↑⍵⊃p}⍨ (67 বাইট)

pভেক্টর একটি ভেক্টর যা হয় p[n][k]এর পার্টিশন সংখ্যা nমধ্যে kসর্বশ্রেষ্ঠ summand সঙ্গে পার্টিশন সংখ্যা: summands, অথবা equivalently k। আমরা pখালি ভেক্টর দিয়ে শুরু করে , পড়াগুলি n( পঠিত ইনপুট) এবং বারবার নিম্নলিখিতগুলি প্রয়োগ করে তৈরি করি:

{⍵,⊂1,⍨+/¨⌽⍵↑¨⍨⌽⍳⍴⍵}
                 ⍴⍵   ⍝ the current length, initially 0
                ⍳⍴⍵   ⍝ 1 2 ... length
               ⌽⍳⍴⍵   ⍝ length ... 2 1
           ⍵↑¨⍨       ⍝ take length elements from p[1], length-1 from p[2], etc
                      ⍝ padded with 0-s, e.g. if p was (,1)(1 1)(1 1 1)(1 2 1 1)(1 2 2 1 1):
                      ⍝ we get:     (1 0 0 0 0)(1 1 0 0)(1 1 1)(1 2)(,1)
          ⌽           ⍝ reverse it: (,1)(1 2)(1 1 1)(1 1 0 0)(1 0 0 0 0)
       +/¨            ⍝ sum each:   1 3 3 2 1
    1,⍨               ⍝ append 1:   1 3 3 2 1 1
 ⍵,⊂                  ⍝ append the above to the vector of vectors

nঅ্যাপ্লিকেশনগুলির পরে ( ⍣⎕), আমরা তৈরি করেছি p

fএকটি এলোমেলো পার্টিশন চয়ন করে। বেশিরভাগ যোগফলগুলির n f kএকটি এলোমেলো পার্টিশন । হয় । kf nn f n

{⍵=0:⍬⋄a,a∇⍵-a←{1++/(?+/⍵)>+\⍵}⍺↑⍵⊃p}⍨
                                     ⍨ ⍝ "selfie" -- use n as k if no k is provided
 ⍵=0:⍬                                 ⍝ if n=0 return empty
                                 ⍵⊃p   ⍝ pick the n-th element of p
                               ⍺↑      ⍝ take k elements from that
               {1++/(?+/⍵)>+\⍵}        ⍝ use them as weights to pick a random number 1...k
               {           +\⍵}        ⍝   partial sums of weights
               {    (?+/⍵)    }        ⍝   a random number 1...sum of weights
               {    (?+/⍵)>+\⍵}        ⍝   which partial sums is it greater than?
               {  +/          }        ⍝   count how many "greater than"-s
               {1+            }        ⍝   we're off by one
             a←                        ⍝ this will be the greatest number in our partition
         a∇⍵-a                         ⍝ recur with n1=n-a and k1=a
       a,                              ⍝ prepend a

কিছু উন্নতি:

  • pসামান্য খারাপ (তবে এখনও যথেষ্ট ভাল) পারফরম্যান্সের মূল্যে ইনলাইন করুন

  • এর গণনার মধ্যে pপুনরায় সাজান এবং 1,একটি চরিত্র সংরক্ষণ

  • সামনে {1++/(?+/⍵)>+\⍵}দিয়ে একটি ট্রেনে পরিণত করুন 1+:1+(+/(?+/)>+\)

  • করতে f একটি বেনামী ফাংশন এবং সরবরাহ একটি আর্গুমেন্ট সম্পূর্ণ প্রোগ্রাম প্রাপ্ত হিসাবে (eval'ed ইনপুট)

{⍵=0:⍬⋄a,a∇⍵-a←1+(+/(?+/)>+\)⍺↑⍵⊃{⍵,⊂⌽1,+/¨⍵↑¨⍨⌽⍳⍴⍵}⍣⍵⊢⍬}⍨⎕ (59 বাইট)

এন = 5 দিয়ে পরীক্ষা করুন

N = 65 দিয়ে পরীক্ষা করুন

এবং নীচের লিঙ্কটি n = 5 হাজার বার বার চলে এবং প্রতিটি বিভাজনের ফ্রিকোয়েন্সি সম্পর্কে পরিসংখ্যান সংগ্রহ করে: ⎕rl←0 ⋄ {⍺,⍴⍵}⌸ {⍵=0:⍬⋄a,a∇⍵-a←1+(+/(?+/)>+\)⍺↑⍵⊃{⍵,⊂⌽1,+/¨⍵↑¨⍨⌽⍳⍴⍵}⍣⍵⊢⍬}⍨ ¨10000⍴5


রজার হুইয়ের সহায়তায় আরও উন্নতি :

  • প্রতিস্থাপন {⍵=0:A⋄B}সঙ্গে {×⍵:B⋄A}। সাইনাম ( ×⍵) সত্য দেয় ⍵>0এবং এর জন্য মিথ্যা⍵=0

  • (+/(?+/)>+\)সঙ্গে প্রতিস্থাপন+/b<?⊃⌽b←+\ , এটি একটি চরিত্র সংরক্ষণ

  • গনা ভেক্টর একটি ম্যাট্রিক্স পরিবর্তে ভেক্টর ব্যবহার p: প্রতিস্থাপন ⍵⊃{⍵,⊂⌽1,+/¨⍵↑¨⍨⌽⍳⍴⍵}⍣⍵⊢⍬সঙ্গে ⊃↓(0,⍨⊢⍪⍨1 1⍉+\)⍣⍵⍪1

{×⍵:a,a∇⍵-a←1++/b<?⊃⌽b←+\⍺↑⊃↓(0,⍨⊢⍪⍨1 1⍉+\)⍣⍵⍪1⋄⍬}⍨ (৫১ বাইট)

পরীক্ষা n = 5 ; পরীক্ষা n = 65 ; freq পরিসংখ্যান


2
একজন কীভাবে রজার হুইয়ের সাহায্য পাবেন?
FUZxxl

5
নিজেকে তাঁর মতো একই সংস্থায় নিয়োগ দেওয়ার জন্য খেলনা এপিএল দোভাষী লিখুন। উপরোক্ত অভিব্যক্তিটিকে একটি চ্যালেঞ্জ হিসাবে ভঙ্গ করুন, তিনি যে সমস্ত চরিত্র গ্রহণ করবেন তার জন্য একটি পিন্ট বিয়ারের প্রতিশ্রুতি দিন। তারপরে লাভ: বিয়ার পান না করায় কম অক্ষর এবং আরও মজাদার।
ngn

1
আমি দেখি. এটি একটি ঝরঝরে কৌশল, আসুন দেখি যে আমি এটি পুনরুত্পাদন করতে পারি কিনা ... আপনি কি তাকে জিজ্ঞাসা করতে পারবেন যে ডায়ালগ এপিএল u/\. yশীঘ্রই যে কোনও সময় জে এর মতো কিছু পেতে চলেছে ?
FUZxxl 21

রেকর্ডের জন্য: twitter.com/FUZxxl/status/572377068555644929
ngn

তাকে জিজ্ঞাসা করার জন্য আপনাকে ধন্যবাদ। এখন আমি ভাবছি যে লিনিয়ার সময়ে এটিও সম্ভব কিনা।
FUZxxl

4

গল্ফস্ক্রিপ্ট, 90 বাইট

~[[[1.]]]\({..[[{{(\{)}%+}%1$,1$,-=}%[1,]@0=+{1+}%]zip{{(\.,/*~}%.,.rand@=+}:^%]\+}*0=^(;`

অনলাইন ডেমো

এটি আমার (সরল) পার্টিশন কাউন্টিং কোডের একটি অভিযোজন যা কেবল একটি গণনা ট্র্যাক করার পরিবর্তে একটি গণনা এবং গণ্য উপাদানগুলির মধ্যে অভিন্নভাবে নির্বাচিত একটিকেই ট্র্যাক করে।

দু'জনের পাশাপাশি তুলনা:

~[[[1.]]]\({..[[{{(\{)}%+}%1$,1$,-=}%[1,]@0=+{1+}%]zip{{(\.,/*~}%.,.rand@=+}:^%]\+}*0=^(;`
 [[ 1  ]]\({..[[{          1$,1$,-=}%  0 @0=+     ]zip{{+}*                }:^%]\+}*0=^

পার্থক্য:

  • প্রথমিক ~ কারণ হ'ল এটি একটি স্নিপেটের চেয়ে প্রোগ্রাম।
  • [1.]প্রতিস্থাপন1 কি পরিবর্তন সাথে সঙ্গতিপূর্ণ ট্র্যাক হচ্ছে।
  • এই {(\{)}%+}%পার্টিশনের প্রতিটি উপাদান অতিরিক্ত বৃদ্ধি করে এবং পার্টিশনে {1+}%যোগ 1করে the
  • 0যা ট্র্যাক করা হয়েছে তার পরিবর্তনের অংশ হিসাবে [0](গল্ফড 1,) হয়ে যায়, তবে অন্যটির কাছে চাপ দেয়ার সময় এটির অ্যারে থাকা দরকার যখন এটি অতিরিক্ত প্রয়োজন[ ]
  • সাধারণ যোগফল {+}* তাদের গণনার যোগফলের সাথে মিলিয়ে পার্টিশনগুলি থেকে একটি ভারী নির্বাচন হয়ে যায়।
  • (;`আউটপুট এবং রাখে পার্টিশন একটা চমৎকার বিন্যাসে থেকে COUNT টি সরিয়ে ফেলা হয়।

পরীক্ষার কাঠামো

;7000,{;
  '5'

  ~[[[1.]]]\({..[[{{(\{)}%+}%1$,1$,-=}%[1,]@0=+{1+}%]zip{{(\.,/*~}%.,.rand@=+}:^%]\+}*0=^(;`

}%
:RESULTS
.&${
  RESULTS.[2$]--,' '\n
}/

আপনি যদি বিভিন্ন সংখ্যক ট্রায়াল চালাতে চান তবে প্রাথমিক 7000 টি টুইট করুন। নোট করুন যে এটি একটি অনলাইন ডেমোটির জন্য খুব ধীর।


3

জাভা, 285 267 বাইট

int[][]p;void p(int n){p=new int[n+1][n+1];int a=n,b=k(n,a),c,d;for(b*=Math.random();n>0;System.out.print(c+" "),n-=a=c)for(c=0;c++<(a<n?a:n)&b>=(d=k(n-c,c));b-=d);}int k(int n,int k){if(p[n][k]<1)for(int a=0,b=0;b<k&b++<n;p[n][k]=a)a+=k(n-b,b);return n>0?p[n][k]:1;}

এটি TheBestOne এর উত্তরের মতো একই পদ্ধতি, তবে এটি মানচিত্রের পরিবর্তে একটি সাধারণ অ্যারে ব্যবহার করে। এছাড়াও, এলোমেলো পার্টিশনটিকে একটি হিসাবে ফিরিয়ে দেওয়ার পরিবর্তে Listএটি কনসোলে তাদের মুদ্রণ করে।

নীচে একটি পরীক্ষা প্রোগ্রাম যা এটি 100000 বার চালায়। উদাহরণস্বরূপ n=5, সমস্ত সেট আমার শেষ রানে নিখুঁত 1/7 এর 0.64% এর মধ্যে ছিল।

public class Partition {
    public static void main(String[] args) {
        Partition p = new Partition();
        for(int i=0;i<100000;i++){
            p.p(5);
            System.out.println();
        }
    }

    int[][]p;

    void p(int n){
        p=new int[n+1][n+1];
        int a=n,b=k(n,a),c,d;
        for(b*=Math.random();n>0;System.out.print(c+" "),n-=a=c)
            for(c=0;c++<(a<n?a:n)&b>=(d=k(n-c,c));b-=d);
    }

    int k(int n,int k){
        if(p[n][k]<1)
            for(int a=0,b=0;b<k&b++<n;p[n][k]=a)
                a+=k(n-b,b);
        return n>0?p[n][k]:1;
    }

}

3
যদিও আপনি golfed থাকেন Math.minনিচে কল (k<n?k:n), আপনি এটি সম্পূর্ণরূপে ditching এবং মাত্র দুই চেক করে আরো যেতে পারেন: b<k&b++<n। আপনি n>0লুপের শর্তসাপেক্ষে সহজেই অংশটি খনন করতে পারেন (যেহেতু কখন অ-নেতিবাচক গ্যারান্টিযুক্ত তা n>0&b<nহ্রাস করে )। b<nb
পিটার টেলর

@ পিটারটেলর ধন্যবাদ আরও একবার নজর দেওয়া আমাকে অতিরিক্ত রিটার্নের বিবৃতি এবং পৃথক intঘোষণা থেকেও মুক্তি পেতে দেয়।
জিওবিটস

3

সিজেম, 64 56 বাইট

ri_L{_0>{\,f{)_@1$-j+}{)@)2$+:Umr@<@@?U+}*}{!a\;}?}2j);p

আপনি এই স্ক্রিপ্ট দিয়ে এটি পরীক্ষা করতে পারেন:

ria100*{_L{_0>{\,f{)_@1$-j+}{)@)2$+:Umr@<@@?U+}*}{!a\;}?}2j);}%__|\f{_,\2$a-,-}2/p

ব্যাখ্যা

ri_                  " Read an integer and duplicate. ";
L{                   " Create a memoized function of the maximum and the sum, which returns
                       a random partition, and the total number of partitions as the last item. ";
    _0>              " If sum > 0: ";
    {
        \,f{         " For I in 0..max-1: ";
            )_@1$-   " Stack: I+1 I+1 sum-I-1 ";
            j+       " Recursively call with the two parameters, and prepend I+1. ";
        }
        {            " Reduce on the results: ";
            )@)2$+   " Stack: partition1 total1 partition2 total1+total2 ";
            :Umr     " U = total1+total2, then generate a random number smaller than that. ";
            @<@@?    " If it is <total1, choose partition1, else choose partition2. ";
            U+       " Append the total back to the array. ";
        }*
    }
    {!a\;}?          " Else return [0] if negative, or [1] if zero. ";
}2j
);p                  " Discard the total and print. ";

2
আপনার উত্তরের "ভুলভাবে খুব ভাল নয়" অংশটি অপসারণ করা উচিত;)
আনাতোলিগ

@ অ্যানাটলিগ সরানো হয়েছে। তবে আমি বিশ্বাস করি কিছু বাইট অপসারণ করা এখনও সম্ভব। আমি এটা করতে খুব অলস।
jimmy23013

3

পাইথ, 64 বাইট

Https://stackoverflow.com/a/2163753/4230423 ব্যবহার বাদে ক) পাইথ যেহেতু কোনও ক্যাশে স্বয়ংক্রিয়ভাবে স্মৃতিচারণ করে না, খ) তালিকায় সংযোজনের পরিবর্তে প্রতিটি প্রিন্ট করে এবং সি) পাইথ অনুবাদ করা হয়।

M?smg-Gddr1hhS,GHG1Akd,QOgQQWQFNr1hhS,QkKg-QNNI<dKB-=dK)N=kN-=QN

আমি সময় পেলে আমি এর ব্যাখ্যা পোস্ট করব, তবে এখানে সম্পর্কিত পাইথন কোডটি এখানে দেওয়া হয়েছে:

g=lambda G,H: sum(map(lambda d:g(G-d, d), range(1, (H if H<G else G) + 1))) if G else 1
Q=input()
k,d = Q,random.randrange(g(Q, Q))
while Q:
    for N in range(1, min(k, Q) + 1):
        K = g(Q-N, N)
        if d < K:
            break
        d -= K
    print N
    k=N
    Q -= N

সম্পাদনা: পরিশেষে আমি ব্যাখ্যাটি করতে পেরেছি:

M                Lambda g(G,H)
 ?         G     If G truthy
  s              Sum
   m             Map
    g            Recursive call
     -Gdd        G-d,d
    r            Range
     1           1 to
     h           +1
      hS         First element of sorted (does min)
       ,GH       From G and H
   1             Else 1
A                Double assign
 kd              Vars k and d
 ,               To vals
  Q              Q (evaled input)
  O              Randrange 0 till val
   gQQ           Call g(Q, Q)
WQ               While Q is truthy
 FN              For N in
  r              Range
   1             From one
   h             Till +1
    hS,QK        Min(Q,K)
  Kg             K=g(
   -QN           Q-N
   N             N
  I<dK           If d<k
   B             Break (implicit close paren)
  -=dk           Subtracts d-=k
 )               Close out for loop
 N               Prints N
 =kN             Set k=N
 -=QN            Subtracts Q-=N

2

অষ্টাভ, 200

function r=c(m)r=[];a=eye(m);a(:,1)=1;for(i=3:m)for(j=2:i-1)a(i,j)=a(i-1,j-1)+a(i-j,j);end;end;p=randi(sum(a(m,:)));while(m>0)b=a(m,:);c=cumsum(b);x=min(find(c>=p));r=[r x];p=p-c(x)+b(x);m=m-x;end;end

Ungolfed:

function r=c(m)
  r=[];
  a=eye(m);
  a(:,1)=1;
  for(i=3:m)
    for(j=2:i-1)
      a(i,j)=a(i-1,j-1)+a(i-j,j);
    end;
  end;
  p=randi(sum(a(m,:)));
  while(m>0)
    b=a(m,:);
    c=cumsum(b);
    x=min(find(cumsum(b)>=p));
    r=[r x];
    p=p-c(x)+b(x);
    m=m-x;
  end
end

বর্গক্ষেত্রের ম্যাট্রিক্স তৈরি করুন যেখানে প্রতিটি সেল (মি, এন) mযার বৃহত্তম সংখ্যার পার্টিশনের সংখ্যা প্রতিফলিত করে n, নুথ এক্সট্র্যাক্ট অনুসারে @ ফেয়ারসাম এত দয়া করে উদ্ধৃত হয়েছে। উদাহরণস্বরূপ, 5,2আমাদের 2 দেয় কারণ দুটি বৈধ পার্টিশন রয়েছে 2,2,1এবং 2,1,1,16,3আমাদের জন্য 3 দেয় 3,1,1,1, 3,2,1এবং 3,3

আমরা এখন নির্বিচারে p'th পার্টিশন খুঁজে পেতে পারি। এখানে, আমরা pএকটি এলোমেলো সংখ্যা হিসাবে উত্পন্ন করছি তবে আপনি স্ক্রিপ্টটি কিছুটা পরিবর্তন করতে পারেন তাই pপরামিতি:

function r=c(m,p)
  r=[];
  a=eye(m);
  a(:,1)=1;
  for(i=3:m)
    for(j=2:i-1)
      a(i,j)=a(i-1,j-1)+a(i-j,j);
    end;
  end;
  while(m>0)
    b=a(m,1:m);
    c=cumsum(b);
    x=min(find(c>=p));
    r=[r x];
    p=p-c(x)+b(x);
    m=m-x;
  end
end

আমরা এখন নির্বিচারে দেখাতে পারি যে প্রতিটি ফলাফল কেবলমাত্র পি এর উপর নির্ভরশীল:

octave:99> for(i=1:7)
> c(5,i)
> end
ans =

   1   1   1   1   1

ans =

   2   1   1   1

ans =

   2   2   1

ans =

   3   1   1

ans =

   3   2

ans =

   4   1

ans =  5

সুতরাং, পি যেখানে এলোমেলোভাবে উত্পাদিত হয় সেখানে ফিরে যাওয়া, আমরা নিশ্চিত হতে পারি যে প্রতিটি ফলাফল সমানভাবেই সম্ভব is


আমি আপনার 5,2 উদাহরণ সম্পর্কে নিশ্চিত নই। দুটি পার্টিশন হওয়া উচিত নয় (2,2,1)এবং (2,1,1,1,1)(যেহেতু আপনি দুটি তালিকাভুক্ত করেছেন তার সংখ্যা বেশি 2) have
মার্টিন ইন্ডার

তুমি ঠিক বলেছ, আমি জিনিসগুলি বাঁকিয়ে ফেলেছি। দুটি উপাদান সহ দুটি পার্টিশন রয়েছে এবং দুটি পার্টিশন দিয়ে শুরু হচ্ছে 2। আমি বোঝাচ্ছি পরেরটি।
dcsohl

2

আর, 198 বাইট

function(m){r=c();a=diag(m);a[,1]=1;for(i in 3:m)for(j in 2:(i-1))a[i,j]=a[i-1,j-1]+a[i-j,j];p=sample(sum(a[m,]),1);while(m>0){b=a[m,];c=cumsum(b);x=min(which(c>=p));r=c(r,x);p=p-c[x]+b[x];m=m-x};r}

Ungolfed:

f <- function(m) {
    r <- c()
    a <- diag(m)
    a[, 1] <- 1
    for (i in 3:m)
        for (j in 2:(i-1))
            a[i, j] <- a[i-1, j-1] + a[i-j, j]
    p <- sample(sum(a[m, ]), 1)
    while (m > 0) {
        b <- a[m, ]
        c <- cumsum(b)
        x <- min(which(c >= p))
        r <- c(r, x)
        p <- p - c[x] + b[x]
        m <- m - x
    }
    return(r)
}

এটি অষ্টাভে @ dcsohl এর দুর্দান্ত সমাধান হিসাবে একই কাঠামো অনুসরণ করে , এবং এইভাবে @feersum দ্বারা পোস্ট করা নথ এক্সট্রাক্টের উপর ভিত্তি করে ।

আমি পরে এটিকে সম্পাদনা করব যদি আমি আর-তে আরও সৃজনশীল সমাধান নিয়ে আসতে পারি the এর মধ্যে, কোনও ইনপুট অবশ্যই স্বাগত।


1

জাভা, 392 বাইট

import java.util.*;Map a=new HashMap();List a(int b){List c=new ArrayList();int d=b,e=b(b,d),f=(int)(Math.random()*e),g,i;while(b>0){for(g=0;g++<Math.min(d, b);f-=i){i=b(b-g,g);if(f<i)break;}c.add(g);d=g;b-=g;}return c;}int b(int b,int c){if(b<1)return 1;List d=Arrays.asList(b,c);if(a.containsKey(d))return(int)a.get(d);int e,f;for(e=f=0;f++<Math.min(c, b);)e+=b(b-f,f);a.put(d,e);return e;}

সাথে কল a(n)। একটি ফেরত পাঠায় Listএর Integerগুলি

ইন্ডেন্টযুক্ত:

import java.util.*;

Map a=new HashMap();

List a(int b){
    List c=new ArrayList();
    int d=b,e=b(b,d),f=(int)(Math.random()*e),g,i;
    while(b>0){
        for(g=0;g++<Math.min(d, b);f-=i){
            i=b(b-g,g);
            if(f<i)
                break;
        }
        c.add(g);
        d=g;
        b-=g;
    }
    return c;
}

int b(int b,int c){
    if(b<1)
        return 1;
    List d=Arrays.asList(b,c);
    if(a.containsKey(d))
        return(int)a.get(d);
    int e,f;
    for(e=f=0;f++<Math.min(c, b);)
        e+=b(b-f,f);
    a.put(d,e);
    return e;
}

Https://stackoverflow.com/a/2163753/4230423 থেকে অভিযোজিত এবং গল্ফড

কিভাবে এই কাজ: আমরা একটি পূর্ণসংখ্যা কত পার্টিশন নিরূপণ করতে পারেন এন হে মধ্যে (আছে এন 2 ) সময়। পার্শ্ব প্রতিক্রিয়া হিসাবে, এটি আকারের একটি টেবিল তৈরি করে ( এন 2 ) যা আমরা তারপরে ও ( এন ) সময়ে , কোনও পূর্ণসংখ্যার কে জন্য এন এর কে বিংশ বিভাজন তৈরি করতে ব্যবহার করতে পারি ।

সুতরাং মোট = পার্টিশনের সংখ্যা। একটি র্যান্ডম নম্বর বাছাই করুন 0 থেকে মোট - 1. জেনারেট করুন ম পার্টিশন।

যথারীতি পরামর্শগুলি স্বাগত :)


1

পাইথন 2, 173 বাইট

from random import*
N,M=input__
R=67;d=[(0,[])]*R*R
for k in range(R*R):p,P=d[k+~R];q,Q=d[k-k%R*R];d[k]=p+q+0**k,[[x+1 for x in Q],[1]+P][random()*(p+q)<p]
print d[N*R+M][1]

Recursively একটি অভিধান তোলে dকী এর মাধ্যমে, kএকজোড়া প্রতিনিধিত্বমূলক (n,m)দ্বারা k=67*n+m(নিশ্চিত ব্যবহার n<=65)। এন্ট্রির পার্টিশন সংখ্যা tuple হয় nমধ্যে mঅংশ, এবং একটি র্যান্ডম যেমন পার্টিশন। গণনাগুলি পুনরাবৃত্ত সূত্র দ্বারা গণনা করা হয় (এটিকে নির্দেশ করার জন্য ফেয়ারসামকে ধন্যবাদ)

f(n,m) = f(n-1,m-1) + f(n,n-m),

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

আমাকে শূন্যের গুণমানগুলি ছাড়িয়ে যেতে mএবং সীমার মান nদিতে অনেক সমস্যা হয়েছিল । প্রথমে, আমি একটি অভিধান ব্যবহার করেছি যা 0 এবং একটি খালি তালিকার গণনায় ডিফল্ট হয়। এখানে, আমি একটি তালিকা ব্যবহার করছি এবং পরিবর্তে এটি এই ডিফল্ট এন্ট্রি দিয়ে প্যাড করছি। নেতিবাচক সূচকগুলি তালিকাটিকে তার শেষ থেকে পড়তে বাধ্য করে, যা একটি ডিফল্ট এন্ট্রি দেয় যা শেষের কাছে পৌঁছানো শেষের মতো কিছুই নয়, এবং রেফ্রাউন্ডগুলি কেবলমাত্র সেই অঞ্চলে স্পর্শ করে m>n


1

80386 মেশিন কোড, 105 বাইট

কোডের হেক্সডাম্প:

60 8b fa 81 ec 00 41 00 00 33 c0 8b f4 33 d2 42
89 14 06 42 33 ed 8b d8 03 2c 1e 2a fa 73 f9 83
c6 04 89 2c 06 42 3b d1 76 ea fe c4 3a e1 76 db
33 d2 0f c7 f0 f7 f5 86 e9 85 d2 74 1b 33 c0 8d
34 0c 39 14 86 77 03 40 eb f8 2b 54 86 fc 40 89
07 83 c7 04 2a e8 77 e1 42 89 17 83 c7 04 fe cd
7f f7 4a b6 41 03 e2 61 c3

সি ফাংশন হিসাবে: void random_partition(int n, int result[]);। সরবরাহিত বাফারে সংখ্যার তালিকা হিসাবে ফলাফলটি প্রদান করে; এটি কোনওভাবেই তালিকার শেষটিকে চিহ্নিত করে না, তবে ব্যবহারকারী সংখ্যা সংগ্রহ করে শেষটি আবিষ্কার করতে পারে - সমষ্টি সমান হলে তালিকাটি শেষ হয় n

কীভাবে ব্যবহার করবেন (ভিজ্যুয়াল স্টুডিওতে):

#include <stdio.h>

__declspec(naked) void __fastcall random_partiton(int n, int result[])
{
#define a(byte) __asm _emit 0x ## byte
a(60) a(8b) a(fa) a(81) a(ec) a(00) a(41) a(00) a(00) a(33) a(c0) a(8b) a(f4) a(33) a(d2) a(42)
a(89) a(14) a(06) a(42) a(33) a(ed) a(8b) a(d8) a(03) a(2c) a(1e) a(2a) a(fa) a(73) a(f9) a(83)
a(c6) a(04) a(89) a(2c) a(06) a(42) a(3b) a(d1) a(76) a(ea) a(fe) a(c4) a(3a) a(e1) a(76) a(db)
a(33) a(d2) a(0f) a(c7) a(f0) a(f7) a(f5) a(86) a(e9) a(85) a(d2) a(74) a(1b) a(33) a(c0) a(8d)
a(34) a(0c) a(39) a(14) a(86) a(77) a(03) a(40) a(eb) a(f8) a(2b) a(54) a(86) a(fc) a(40) a(89)
a(07) a(83) a(c7) a(04) a(2a) a(e8) a(77) a(e1) a(42) a(89) a(17) a(83) a(c7) a(04) a(fe) a(cd)
a(7f) a(f7) a(4a) a(b6) a(41) a(03) a(e2) a(61) a(c3)
}

void make_stack() // see explanations about stack below
{
    volatile int temp[65 * 64];
    temp[0] = 999;
}

int main()
{
    int result[100], j = 0, n = 64, counter = n;
    make_stack(); // see explanations about stack below

    random_partiton(n, result);

    while (counter > 0)
    {
        printf("%d ", result[j]);
        counter -= result[j];
        ++j;
    }
    putchar('\n');
}

উদাহরণ আউটপুট (এন = 64 সহ):

21 7 4 4 3 3 3 2 2 2 2 2 1 1 1 1 1 1

এর জন্য অনেক ব্যাখ্যা প্রয়োজন ...

অবশ্যই আমি সেই অ্যালগরিদম ব্যবহার করেছি যা প্রত্যেকে প্রত্যেকে ব্যবহার করেছেন; জটিলতা সম্পর্কে প্রয়োজনীয়তার সাথে কোনও পছন্দ ছিল না। সুতরাং আমি খুব বেশি অ্যালগরিদম ব্যাখ্যা করতে হবে না। যাই হোক:

আমি এর চেয়ে বেশি অংশ ব্যবহার করে উপাদানগুলির f(n, m)বিভাজন সংখ্যা দ্বারা বোঝাচ্ছি । আমি এগুলিকে 2-ডি অ্যারে (সি হিসাবে ঘোষিত ) সংরক্ষণ করি, যেখানে প্রথম সূচক এবং দ্বিতীয়টি । আমি সিদ্ধান্ত নিয়েছি যে সমর্থনnmf[65][64]nm-1n=65 করা খুব বেশি সমস্যা ছিল, তাই এটিকে ত্যাগ করুন ...

এই কোডটি গণনা করে এখানে সি কোড রয়েছে:

#define MAX_M 64
int f[(MAX_M + 1) * MAX_M];
int* f2;
int c; // accumulates the numbers needed to calculate f(n, m)
int m;
int k; // f(k, m), for various values of k, are accumulated
int n1;

for (n1 = 0; n1 <= n; ++n1)
{
    f2 = f;
    f2[n1 * MAX_M] = 1;
    for (m = 2; m <= n; ++m)
    {
        c = 0;
        k = n1;
        while (k >= 0)
        {
            c += f2[k * MAX_M];
            k -= m;
        }
        ++f2;
        f2[n1 * MAX_M] = c;
    }
}

এই কোডটির কিছু অস্পষ্ট শৈলী রয়েছে, তাই এটি সহজেই সমাবেশ ভাষায় রূপান্তর করা যায়। এটি অবধি উপাদানসমূহ গণনা করে f(n, n), যা nউপাদানগুলির বিভাজনের সংখ্যা । যখন এই কোডটি শেষ হয়, অস্থায়ী পরিবর্তনশীলটিতে cপ্রয়োজনীয় নম্বর থাকে যা একটি এলোমেলো পার্টিশন নির্বাচন করতে ব্যবহার করা যেতে পারে:

int index = rand() % c;

পরে, indexউত্পাদিত টেবিলটি ব্যবহার করে এটি প্রয়োজনীয় বিন্যাসে (সংখ্যার তালিকায়) রূপান্তরিত হয়।

do {
    if (index == 0)
        break;

    m = 0;
    f2 = &f[n * MAX_M];
    while (f2[m] <= index)
    {
        ++m;
    }

    index -= f2[m-1];
    ++m;
    *result++ = m;
    n -= m;
} while (n > 0);

do {
    *result++ = 1;
    --n;
} while (n > 0);

এই কোডটি সমাবেশ ভাষায় রূপান্তর করার জন্যও অনুকূলিত। একটি ছোট "বাগ" রয়েছে: পার্টিশনটিতে যদি 1শেষে কোনও সংখ্যা না থাকে , শেষ লুপটি মুখোমুখি হয় n = 0এবং বিনা শর্তে আউটপুট দেয়1 উপাদানকে । এটি কোনও ক্ষতি করে না, কারণ মুদ্রণ কোডটি সংখ্যার যোগফল ট্র্যাক করে এবং এই বহিরাগত সংখ্যাটি মুদ্রণ করে না।

ইনলাইন অ্যাসেমব্লিতে রূপান্তরিত হওয়ার পরে, এই কোডটি এর মতো দেখায়:

__declspec(naked) void _fastcall random_partition_asm(int n, int result[])
{
    _asm {
        pushad;

        // ecx = n
        // edx = m
        // bh = k; ebx = k * MAX_M * sizeof(int)
        // ah = n1; eax = n1 * MAX_M * sizeof(int)
        // esp = f
        // ebp = c
        // esi = f2
        // edi = result

        mov edi, edx;
        sub esp, (MAX_M + 1) * MAX_M * 4; // allocate space for table
        xor eax, eax;
    row_loop:
        mov esi, esp;
        xor edx, edx;
        inc edx;
        mov dword ptr [esi + eax], edx;
        inc edx;

    col_loop:
        xor ebp, ebp;
        mov ebx, eax;

    sum_loop:
        add ebp, [esi + ebx];
        sub bh, dl;
        jae sum_loop;

        add esi, 4;
        mov [esi + eax], ebp;
        inc edx;
        cmp edx, ecx;
        jbe col_loop;

        inc ah;
        cmp ah, cl;
        jbe row_loop;

        // Done calculating the table

        // ch = n; ecx = n * MAX_M * sizeof(int)
        // eax = m
        // ebx = 
        // edx = index
        // esp = f
        // esi = f2
        // ebp = c
        // edi = result

        xor edx, edx;
        rdrand eax; // generate a random number
        div ebp; // generate a random index in the needed range
        xchg ch, cl; // multiply by 256

    n_loop:
        test edx, edx;
        jz out_trailing;
        xor eax, eax;
        lea esi, [esp + ecx];

    m_loop:
        cmp [esi + eax * 4], edx;
        ja m_loop_done;
        inc eax;
        jmp m_loop;
    m_loop_done:

        sub edx, [esi + eax * 4 - 4];
        inc eax;
        mov [edi], eax;
        add edi, 4;
        sub ch, al;
        ja n_loop;

    out_trailing:
        inc edx;
    out_trailing_loop:
        mov dword ptr [edi], edx;
        add edi, 4;
        dec ch;
        jg out_trailing_loop;

        dec edx;
        mov dh, (MAX_M + 1) * MAX_M * 4 / 256;
        add esp, edx;
        popad;
        ret;
    }
}

কিছু মজার বিষয় লক্ষ্য করুন:

  • একটি এলোমেলো সংখ্যা তৈরি করতে মেশিন কোডের মাত্র 3 বাইট লাগে (rdrand নির্দেশনা)
  • কাকতালীয়ভাবে, টেবিলের আকার 64৪, তাই এক সারির আকার 256 বাইট। আমি এটি "হাই-বাইট" রেজিস্টারগুলিতে সারি সূচকগুলি ধরে রাখতে ব্যবহার করি ah, যা আমাকে 256 দ্বারা স্বয়ংক্রিয় গুণিত দেয় this এর সুবিধা নিতে আমি সমর্থনটির জন্য আত্মত্যাগ করেছি n = 65। আমি আশা করি আমি এই পাপের জন্য ক্ষমা হতে পারি ...
  • স্ট্যাকের স্থান বরাদ্দ করা স্ট্যাক পয়েন্টার রেজিস্টার থেকে 0x4100 বিয়োগ করে সম্পাদিত হয় esp। এটি একটি 6-বাইট নির্দেশ! এই নম্বরটি আবার যুক্ত করার সময়, আমি এটি 5 বাইটে পরিচালনা করতে পেরেছি:

        dec edx; // here edx = 1 from earlier calculations
        mov dh, (MAX_M + 1) * MAX_M * 4 / 256; // now edx = 0x4100
        add esp, edx; // this deallocates space on stack
    
  • এমএস ভিজ্যুয়াল স্টুডিওতে এই ফাংশনটি ডিবাগ করার সময়, আমি আবিষ্কার করেছি যে এটি স্ট্যাকের জন্য বরাদ্দকৃত স্থানটিতে ডেটা লেখার সময় এটি ক্র্যাশ হয়ে যায়! কিছুটা খনন করার পরে, আমি এক ধরণের স্ট্যাক ওভাররন সুরক্ষা আবিষ্কার করেছি: ওএস মনে হচ্ছে স্ট্যাকের জন্য খুব সীমিত ভার্চুয়াল ঠিকানাগুলি বরাদ্দ করেছে; যদি কোনও ফাংশন খুব দূরের কোনও ঠিকানাতে অ্যাক্সেস করে তবে ওএস ধরে নেয় যে এটি ছাড়িয়ে গেছে এবং প্রোগ্রামটি মেরে ফেলে। যাইহোক, যদি কোনও ফাংশনে অনেক স্থানীয় ভেরিয়েবল থাকে তবে ওএস এটিকে কাজ করতে কিছু অতিরিক্ত "যাদু" করে। সুতরাং আমাকে একটি খালি ফাংশন কল করতে হবে যাতে স্ট্যাকের জন্য বড় অ্যারে বরাদ্দ রয়েছে। এই ফাংশনটি ফেরার পরে, অতিরিক্ত স্ট্যাক ভিএম পৃষ্ঠাগুলি বরাদ্দ করা হয় এবং এটি ব্যবহার করা যেতে পারে।

        void make_stack()
        {
            volatile int temp[65 * 64];
            temp[0] = 999; // have to "use" the array to prevent optimizing it out
        }
    
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.