তুমিই কি সেই একজন? (মাস্টারমাইন্ড ডেরিভেটিভ)


15

আমি আপনার জন্য একটি কঠিন পেয়েছি!

আমার বান্ধবীটি সম্প্রতি এমটিভিতে (মার্কিন যুক্তরাষ্ট্র) একটি নতুন শো জুড়ে এসেছিল। এটি একটি ভয়ানক শো, এবং এর প্রত্যেকেই ট্র্যাশযুক্ত তবে "গেম "টি বেশ আকর্ষণীয়। উইকিপিডিয়া থেকে:

তুমিই কি সেই একজন? হাওয়াইয়ে একত্রে বসবাসকারী 20 জনকে তাদের নিখুঁত ম্যাচটি অনুসন্ধান করতে অনুসরণ করে। যদি 10 জন পুরুষ এবং 10 জন মহিলা দশ সপ্তাহের মধ্যে সমস্ত দশটি নিখুঁত ম্যাচ সঠিকভাবে চয়ন করতে সক্ষম হয় তবে তাদের মধ্যে বিভক্ত হওয়ার জন্য তারা $ 1 মিলিয়ন লাভ করবে।

এখন খেলার অংশের জন্য (উইকিপিডিয়া থেকেও):

প্রতিটি পর্বই কাস্টের সাথে জুটি বেঁধে তারা বিশ্বাস করে যে তাদের চূড়ান্ত ম্যাচটি চ্যালেঞ্জের সাথে প্রতিযোগিতা করা to চ্যালেঞ্জের বিজয়ীরা তারিখে যাবে এবং সত্যের বুথে তাদের ম্যাচটি পরীক্ষা করার সুযোগ পাবে। কাস্ট মেম্বাররা বিজয়ী দম্পতিদের মধ্যে একটি বেছে নেবেন সত্যের বুথে যেতে তারা নিখুঁত ম্যাচ কিনা তা নির্ধারণ করতে। এটি ম্যাচগুলি নিশ্চিত করার একমাত্র উপায়। প্রতিটি পর্বের সমাপ্তি অনুষ্ঠানের সাথে শেষ হয় যেখানে দম্পতিদের বলা হবে তাদের কতটি নিখুঁত ম্যাচ আছে তবে কোন মিলগুলি সঠিক নয়।

টিএল; ডিআর: এটি একটি মাস্টারমাইন্ড ডেরিভেটিভ (নির্দিষ্ট করে দেওয়ার জন্য এম (10,10))। গেমের নিয়মগুলি নিম্নরূপ:

  1. আপনি 10 এর 2 টি সেট দিয়ে শুরু করুন, আসুন তাদের সেট এ: {এ, বি, সি, ডি, ই, এফ, জি, এইচ, আই, জে এবং সেট 2: 2 1,2,3,4,5, 6,7,8,9,10}

  2. কম্পিউটার solution A1, B2, C3, D4, E5, F6, G7, H8, I9, J10 form আকারে একটি সমাধান তৈরি করে (আপনার কাছে দৃশ্যমান নয়), যেখানে সেট এ-এর সদস্যরা 1-থেকে -1 ম্যাপ করা হয়েছে 2 সেট করতে a A2, B5, C10, D8, E1, F7, G6, H4, I9, J3 a সমাধানের আর একটি উদাহরণ হতে পারে}

  3. আপনার প্রথম পালা দেওয়ার আগে, আপনাকে জিজ্ঞাসা করতে হবে যে আপনার পছন্দের কোনও একক, নির্দিষ্ট জুটি সঠিক কিনা। আপনার প্রশ্নটি {A1} (যেমন {C8}) আকারে হবে এবং আপনি একটি 1 (অর্থ সঠিক) বা 0 (যার অর্থ আপনার অনুমানটি ভুল) receive

  4. আপনার প্রথম আসল পালা। আপনি নিজের প্রথম অনুমানটি {এ 1, বি 2, সি 3, ডি 4, ই 5, এফ 6, জি 7, এইচ 8, আই 9, জ 10}, বা আপনার পছন্দের যেকোন অনুমান আকারে তৈরি করতে পারেন। আপনার অনুমানের মধ্যে কোনও আইটেমের গুণক যেমন {এ 1, এ 2, এ 3, এ 4, এ 5, বি 6, বি 7, বি 8, বি 9, বি 10 contain অনুমান একটি বৈধ অনুমান নয়। প্রতিটি টার্নের পরে, কম্পিউটার আপনাকে সঠিক মিলগুলির সংখ্যা বলে , তবে কোন মিলগুলি সঠিক তা নয়।

  5. আপনি প্রতিটি ম্যাচ সঠিক না হওয়া অবধি 3 এবং 4 ধাপ পুনরাবৃত্তি করুন (অর্থাত 10 এর প্রতিক্রিয়া), বা আপনার 10 টি চালগুলি শেষ না হওয়া অবধি (যত তাড়াতাড়ি হোক)। আপনি যদি এটি 10 ​​ম বারের আগে বা এটিকে সমাধান করেন তবে আপনি million 1 মিলিয়ন জিতবেন। অন্যথায়, আপনি হেরে গেছেন এবং কিছু লোক (বা চিঠি এবং সংখ্যা) তাদের 10 বিড়ালের সাথে অনন্তকাল কাটাতে একা বাড়িতে চলে যায়।

এটি একটি সংক্ষিপ্ত কোড প্রতিযোগিতা নয়। যে ব্যক্তি কমপক্ষে গড় অনুমানের সংখ্যাটিতে একটি এলোমেলো ম্যাচটি সমাধান করতে পারে সে বিজয়ী হবে be চতুর গেম প্লে এবং গণনার গতিও সম্ভবত এটির কারণ হতে পারে I আমি ধরে নিচ্ছি গড় টার্নের সংখ্যা প্রায় অবশ্যই 10 এর বেশি হবে, সুতরাং আপনার 1 মিলিয়ন ডলার পুরষ্কার (সম্ভবত এমটিভি দ্বারা প্রদত্ত, সম্ভবত আমি নয়) পাতলা পাতলা is শুধু কিভাবে এটা অসম্ভব ঢালাই গ্র্যান্ড পুরস্কার জয় জন্য?

দ্রষ্টব্য: এটিকে {এ 1, বি 2, ...} ফর্ম্যাটে রাখার প্রয়োজন নেই। ধাঁধাটি কী তা একেবারে পরিষ্কার করার জন্য আমি প্রশ্নটিতে সেই ফর্মটি ব্যবহার করেছি। আপনি যদি এই ফর্মটিতে না রাখেন তবে দয়া করে কীভাবে এটি কল করবেন তা ব্যাখ্যা করুন।

শুভকামনা!


3
আপনি ব্যক্তি যিনি জয় অন্তত গড় অনুমান এটা সমাধান করতে পারেন, কেন না যে বিজয়ী মানদণ্ড? পুরোপুরি কার্যকর বৈধ শর্তটি যখন আমাদের মুখে ঝকঝকে করছে তখন আমি জনপ্রিয়তার প্রতিযোগিতা হওয়ার কোনও কারণ দেখতে পাচ্ছি না।
জিওবিটস

যতদূর আমি প্রশ্নটি বলতে পারি সর্বোত্তমভাবে মাস্টারমাইন্ড খেলার সাথে কোনও সম্পর্ক নেই। এটি এমন একটি গেমের জন্য জিজ্ঞাসা করে যা কোনও ব্যবহারকারী এটি খেলতে দেয়।
feersum

1
তাহলে পপ-প্রতিযোগিতা এটির জন্য ট্যাগ নয়।

1
@ হোস্টচ 250 বিজয়ীর জন্য আপডেট হওয়া মানদণ্ড
dberm22

2
7 টি upvotes, 2 পছন্দসই, এবং কোন উত্তর নেই। আমি জানতাম এটি ছিল শক্ত!
dberm22

উত্তর:


6

পাইথন 2 (পাইপি ব্যবহার করে চালানো হলে দ্রুত চালান)

প্রায় সবসময় 10 রাউন্ড বা তার চেয়ে কমের মধ্যে সঠিক জুটি অনুমান করার জন্য বিশ্বাসী

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

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

যাইহোক, যদি এটি বাস্তব জীবনের শোতে ব্যবহৃত হয় তবে পরবর্তী রাউন্ডের (এক সপ্তাহ?) আগে এর যথেষ্ট পরিমাণ সময় থাকতে পারে তাই এই অ্যালগরিদমটি বাস্তব জীবনে ব্যবহার করতে পারে = ডি

সুতরাং আমি মনে করি এটি নিরাপদ বলে মনে করি যে এটি গড়ে 10 টি অনুমান বা তার চেয়ে কম ক্ষেত্রে সঠিক জুটি পেতে পারে।

এটি নিজে চেষ্টা করো. এটা কঠিন বলে মনে হয় আরও উন্নত করার জন্য তাই আমি ঠিক কোড হিসাবে ছেড়ে দেব আমি শুধু র্যান্ডম পিক করছেন চেষ্টা করেছি, কিন্তু এমনকি। আমি আগামী কয়েক দিনের (সম্পাদনা মধ্যে গতি বাড়াতে পারে size=7, এটা 5040 মামলা 3 ব্যর্থ , তাই আমি চালক পদ্ধতিটি রাখার সিদ্ধান্ত নিয়েছি)। আপনি এটি হিসাবে চালাতে পারেন:

pypy are_you_the_one.py 10

অথবা, আপনি কীভাবে এটি কাজ করে তা যদি দেখতে চান তবে ছোট সংখ্যাকে ইনপুট করুন (যাতে এটি দ্রুত চলে)

একটি সম্পূর্ণ পরীক্ষা চালানোর জন্য (সতর্কতা: এটি size> 7 এর জন্য খুব বেশি সময় নিবে), একটি নেতিবাচক নম্বর দিন।

এর জন্য সম্পূর্ণ পরীক্ষা size=7(2 মি 32 সেকেন্ডে সম্পূর্ণ):

...
(6, 5, 4, 1, 3, 2, 0): 5 অনুমান
(6, 5, 4, 2, 0, 1, 3): 5 অনুমান
(6, 5, 4, 2, 0, 3, 1): 4 অনুমান
(6, 5, 4, 2, 1, 0, 3): 5 অনুমান
(6, 5, 4, 2, 1, 3, 0): 6 অনুমান
(6, 5, 4, 2, 3, 0, 1): 6 অনুমান
(6, 5, 4, 2, 3, 1, 0): 6 অনুমান
(6, 5, 4, 3, 0, 1, 2): 6 অনুমান
(6, 5, 4, 3, 0, 2, 1): 3 অনুমান
(6, 5, 4, 3, 1, 0, 2): 7 অনুমান
(6, 5, 4, 3, 1, 2, 0): 7 অনুমান
(6, 5, 4, 3, 2, 0, 1): 4 অনুমান
(6, 5, 4, 3, 2, 1, 0): 7 অনুমান
গড় গণনা: 5.05
সর্বাধিক গণনা: 7
সর্বনিম্ন গণনা: 1
সাফল্যের সংখ্যা: 5040

যদি RANDOM_THRESHOLDএবং CLEVER_THRESHOLDউভয়ই খুব উচ্চ মানের (50000 এর মতো) হিসাবে সেট করা থাকে তবে এটি সবচেয়ে বেশি অনুমানযোগ্য অবস্থার সম্ভাবনার সংখ্যাটি হ্রাস করে এমন অনুকূল অনুমানের জন্য অ্যালগরিদমকে বাধ্য করবে। এটি খুব ধীর, তবে খুব শক্তিশালী। উদাহরণস্বরূপ, এটি চালিয়ে যাওয়া size=6দৃ as়ভাবে জানায় যে এটি সর্বোচ্চ 5 টি রাউন্ডে সঠিক জুড়িগুলি খুঁজে পেতে পারে।

যদিও গড় আনুমানিক ব্যবহারের সাথে তুলনা করা বেশি (যা গড়ে 4.11 রাউন্ড) তবে এটি সর্বদা সফল হয়, আরও এক গোল বাদে আরও বেশি। এটি আমাদের অনুমানকে আরও দৃ strengthen় করে তোলে যে যখন size=10এটি প্রায় 10 রাউন্ড বা তারও কম সময়ে সঠিক জুটি পাওয়া উচিত।

ফলাফল (3 মি 9s এ সমাপ্ত):

(5, 4, 2, 1, 0, 3): 5 অনুমান
(5, 4, 2, 1, 3, 0): 5 অনুমান
(5, 4, 2, 3, 0, 1): 4 টি অনুমান
(5, 4, 2, 3, 1, 0): 4 টি অনুমান
(5, 4, 3, 0, 1, 2): 5 অনুমান
(5, 4, 3, 0, 2, 1): 5 অনুমান
(5, 4, 3, 1, 0, 2): 5 অনুমান
(5, 4, 3, 1, 2, 0): 5 অনুমান
(5, 4, 3, 2, 0, 1): 5 অনুমান
(5, 4, 3, 2, 1, 0): 5 অনুমান
গড় গণনা: 4.41
সর্বাধিক গণনা: 5
সর্বনিম্ন গণনা: 1
সাফল্যের সংখ্যা: 720

কোড.

from itertools import permutations, combinations
import random, sys
from collections import Counter

INTERACTIVE = False
ORIG_PERMS = []
RANDOM_THRESHOLD = 100
CLEVER_THRESHOLD = 0

class Unbuffered():
    def __init__(self, stream):
        self.stream = stream

    def write(self, data):
        self.stream.write(data)
        self.stream.flush()

    def __getattr__(self, attr):
        self.stream.getattr(attr)
sys.stdout = Unbuffered(sys.stdout)

def init(size):
    global ORIG_PERMS
    ORIG_PERMS = list(permutations(range(size)))

def evaluate(solution, guess):
    if len(guess) == len(solution):
        cor = 0
        for sol, gss in zip(solution, guess):
            if sol == gss:
                cor += 1
        return cor
    else:
        return 1 if solution[guess[0]] == guess[1] else 0

def remove_perms(perms, evaluation, guess):
    return [perm for perm in perms if evaluate(perm, guess)==evaluation]

def guess_one(possible_perms, guessed_all, count):
    if count == 1:
        return (0,0)
    pairs = Counter()
    for perm in possible_perms:
        for pair in enumerate(perm):
            pairs[pair] += 1
    perm_cnt = len(possible_perms)
    return sorted(pairs.items(), key=lambda x: (abs(perm_cnt-x[1]) if x[1]<perm_cnt else perm_cnt,x[0]) )[0][0]

def guess_all(possible_perms, guessed_all, count):
    size = len(possible_perms[0])
    if count == 1:
        fact = 1
        for i in range(2, size):
            fact *= i
        if len(possible_perms) == fact:
            return tuple(range(size))
        else:
            return tuple([1,0]+range(2,size))
    if len(possible_perms) == 1:
        return possible_perms[0]
    if count < size and len(possible_perms) > RANDOM_THRESHOLD:
        return possible_perms[random.randint(0, len(possible_perms)-1)]
    elif count == size or len(possible_perms) > CLEVER_THRESHOLD:
        (_, next_guess) = min((max(((len(remove_perms(possible_perms, evaluation, next_guess)), next_guess) for evaluation in range(len(next_guess))), key=lambda x: x[0])
                               for next_guess in possible_perms if next_guess not in guessed_all), key=lambda x: x[0])
        return next_guess
    else:
        (_, next_guess) = min((max(((len(remove_perms(possible_perms, evaluation, next_guess)), next_guess) for evaluation in range(len(next_guess))), key=lambda x: x[0])
                               for next_guess in ORIG_PERMS if next_guess not in guessed_all), key=lambda x: x[0])
        return next_guess

def main(size=4):
    if size < 0:
        size = -size
        init(size)
        counts = []
        for solution in ORIG_PERMS:
            count = run_one(solution, False)
            counts.append(count)
            print '%s: %d guesses' % (solution, count)
        sum_count = float(sum(counts))
        print 'Average count: %.2f' % (sum_count/len(counts))
        print 'Max count    : %d' % max(counts)
        print 'Min count    : %d' % min(counts)
        print 'Num success  : %d' % sum(1 for count in counts if count <= size)
    else:
        init(size)
        solution = ORIG_PERMS[random.randint(0,len(ORIG_PERMS)-1)]
        run_one(solution, True)

def run_one(solution, should_print):
    if should_print:
        print solution
    size = len(solution)
    cur_guess = None
    possible_perms = list(ORIG_PERMS)
    count = 0
    guessed_one = []
    guessed_all = []
    while True:
        count += 1
        # Round A, guess one pair
        if should_print:
            print 'Round %dA' % count
        if should_print:
            print 'Num of possibilities: %d' % len(possible_perms)
        cur_guess = guess_one(possible_perms, guessed_all, count)
        if should_print:
            print 'Guess: %s' % str(cur_guess)
        if INTERACTIVE:
            evaluation = int(raw_input('Number of correct pairs: '))
        else:
            evaluation = evaluate(solution, cur_guess)
            if should_print:
                print 'Evaluation: %s' % str(evaluation)
        possible_perms = remove_perms(possible_perms, evaluation, cur_guess)

        # Round B, guess all pairs
        if should_print:
            print 'Round %dB' % count
            print 'Num of possibilities: %d' % len(possible_perms)
        cur_guess = guess_all(possible_perms, guessed_all, count)
        if should_print:
            print 'Guess: %s' % str(cur_guess)
        guessed_all.append(cur_guess)
        if INTERACTIVE:
            evaluation = int(raw_input('Number of correct pairs: '))
        else:
            evaluation = evaluate(solution, cur_guess)
            if should_print: print 'Evaluation: %s' % str(evaluation)
        if evaluation == size:
            if should_print:
                print 'Found %s in %d guesses' % (str(cur_guess), count)
            else:
                return count
            break
        possible_perms = remove_perms(possible_perms, evaluation, cur_guess)

if __name__=='__main__':
    size = 4
    if len(sys.argv) >= 2:
        size = int(sys.argv[1])
        if len(sys.argv) >= 3:
            INTERACTIVE = bool(int(sys.argv[2]))
    main(size)

এটি সত্যই অবিশ্বাস্য। আমি এটি আরও 100 বার চালিয়েছি, এবং সমাধানটি খুঁজে পেতে 10 টিরও বেশি অনুমান করা এখনও বাকি আছে। আমি একটি দম্পতি 10 এবং এমনকি একটি দম্পতি 6 এরও দেখেছি। (আপনি বলছেন যে আপনি এমন কোনও দৃষ্টান্ত দেখেন নি যেখানে এটি 10 ​​রাউন্ডের নীচে সঠিক জুটি বাঁধতে পারে না That সম্ভবত এটি "10 বা কম রাউন্ডে" বলতে হবে, তবে এটি কেবল শব্দার্থক)) এটি দুর্দান্ত is আমি ধরে নিচ্ছি আপনার ল্যাম্বডা মানটি এনট্রপির এক ধরণের পরিমাপ যা আপনাকে সর্বোত্তম অনুমান করতে দেয়, তবে কীভাবে বা কোথায় সেট করা হয়েছে তা আমি দেখতে পাই না। এটি কেবল আমার ঘন হওয়া, আপনার কর্মসূচির কোনও ইন্ডিকেট নয়। অবিশ্বাস্য কাজ!
dberm22

এটি সবচেয়ে খারাপ পরিস্থিতিতে ( len(remove_perms ...)অংশ) থাকা সম্ভাবনার সংখ্যা হ্রাস করার চেষ্টা করছে । এবং হ্যাঁ, আমি <= 10 রাউন্ডে =) বোঝাতে চাইছি। উপরের কোডটিতে বিটিডব্লিউটি কখনই অনুকূল অনুমান করা হয় না, যেহেতু আমি রেখেছি CLEVER_THRESHOLD=0, যার অর্থ এটি কেবল সম্ভাবনার তালিকা থেকে অনুমান করার চেষ্টা করবে, যদিও সর্বোত্তম অনুমান এই সেটটির বাইরে থাকতে পারে। তবে সময় বাঁচাতে আমি সেটি অক্ষম করার সিদ্ধান্ত নিয়েছি। আমি size=7সর্বদা সফল হয় তা দেখিয়ে এর জন্য সম্পূর্ণ পরীক্ষা যুক্ত করেছি ।
justhalf

1
আমি রাতারাতি আপনার কোডটি 'চতুর থ্রেশহোল্ড = 0' দিয়ে চালিয়ে যাচ্ছি (9,8,7,6,5,4,3,2,1,0 থেকে শুরু করে এবং সমস্ত আদেশের মাধ্যমে পিছনে কাজ করছি)। আমি এখনও পর্যন্ত কেবল 2050 এর মধ্যে রয়েছি, তবে এখানে 13 টি ঘটনা ঘটেছে যেখানে এটি 11 টি টার্ন নিয়েছে। নমুনা মুদ্রণ - (9, 8, 7, 4, 0, 6, 3, 2, 1, 5): 9 অনুমান, গড় গণনা: 8.29, সর্বাধিক গণনা: 11, ন্যূনতম সংখ্যা: 4, সংখ্যা সাফল্য: 2037, সংখ্যা মূল্যায়ন: 2050. যদি 'চালাক থ্রেশহোল্ড' সঠিকভাবে সেট করা থাকে তবে আমি বাজি ধরেছি যে 11 টি 10 ​​এর দশকে পরিণত হবে। তবুও, গড়ে, 8.3 বেশ চমত্কার।
dberm22

@ dberm22: হ্যাঁ, রাতারাতি এই ধীর অ্যালগরিদমটি চালানোর জন্য আপনাকে ধন্যবাদ! আমি সম্পূর্ণ পরীক্ষা size=8চালিয়েছি এবং দেখতে পেয়েছি যে যদি এই সেটিংটি ব্যবহার করা হয় তবে সর্বশেষ সংস্করণটিতে কেবল 40308 সাফল্য রয়েছে (40320 এর পরিবর্তে)। তবে এটি এখনও 99.97% সাফল্যের হার! অনুমান করুন যে আমরা টিভি শোয়ের সংগঠককে দেউলিয়া করে তুলতে পারি।
justhalf

3

সিজে্যাম -19 টার্নস - একটি ইডিয়টসের কৌশল

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

আপডেট: নীচের কোডটি রাষ্ট্রের ব্যবহারের জন্য আপডেট করা হয়েছিল যে কেবলমাত্র যদি ইতিমধ্যে আমরা জানতাম যে সঠিকভাবে সঠিক ছিল সেগুলি কার্যকর হয় না এমনগুলি মুছে ফেলা উচিত। এটি আমার এলোমেলো "সঠিক উত্তর" জেনারেটর দেখানোর জন্যও সম্পাদনা করা হয়েছিল। গড় ফলাফল এখন কেবল 19. এটি এখনও একটি বোবা সমাধান তবে এটি আগের প্রান্তিকের চেয়ে ভাল।

A,{__,mr=_@@-}A*;]sedS*:Z;

ZS/:i:G;                               "Set the input (goal) to G";
{UU@{G2$==@+\)}%~;}:C;                 "This is the tool to count how many of an array agree with G";
{:Y;1$1$<{Y-}%Yaa+@@)>{Y-}%+}:S;       "for stack A X Y, sets the Xth value in the array to Y";
{:Y;1$1$<2$2$=Y-a+@@)>+}:R;            "for stack A X Y, removes Y from the Xth value in the array";

1:D;                                   "Set turn counter to one. if zero exits loop";

A,]A*                                  "array of arrays that has all possible values for an ordering";

{                                      "start of loop";

_V=(\;_GV=={V\SV):V;}{V\R}?            "Guesses a number for the first unknown. If right sets the pair; else erases it";

_[{(_,_{mr=}{;;11}?:Y\{Y-}%}A*;]_C     "guesses random possible arrangement and determines how many are right, error=11";
\_{+}*45-:Y{Y;{_11={;BY-}{}?}%}{}?\    "error correct by including the missing number";

_V={;V:X>{X\RX):X;}%~LV}{}?            "if all new are wrong, makes sure they aren't guessed again";
_A={Dp0:D;;p;}{D):D;;;}?               "If all are right, prints it an tells loop to exit.  Else increments counter";

D}g                                    "repeat from start of loop";

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

একটি সমাধান বাস্তবায়নের জন্য যথেষ্ট সাহসী হওয়ার জন্য +1। আমি আসলেই বেশ হতবাক হয়েছি যে সঠিক সমাধান অনুমান করতে এটি গড়ে 27 টি করে সময় নেয়। আমি ধরে নিয়েছি যে আপনি সঠিক অনুমান হিসাবে, পরবর্তী ম্যাচগুলি তাত্পর্যপূর্ণভাবে (ভাল, তাত্ত্বিকভাবে) সন্ধান করা সহজ। ধন্যবাদ! কেউ যদি ১০ এর চেয়ে কম পেতে পারে তবে আমি আগ্রহী You আপনি আমাকে আশা দিয়েছেন!
dberm22

27 যদি অবাক হয় যে তাকান! সমস্ত ঠাট্টা-বিদ্রূপ আমি মনে করি যে একটি সমাধান যা গ্যারান্টি দেয় 10 বা কমপক্ষে গড়ে এটি পাওয়া সম্ভব। আমি যুক্তিসঙ্গত সময় ফ্রেমে কাজ করার জন্য এই জাতীয় অ্যালগরিদম পেতে পারি না।
কেইন

১৯ ... আমি আরও বেশি হতবাক যদিও আপনার প্রোগ্রামে কেবল একটি প্রশ্ন ... যেখানে আপনি বলেছেন "প্রথম অজানাটির জন্য একটি সংখ্যা অনুমান করে right যদি ডান জোড় সেট করে; অন্যথায় এটি মুছে ফেলে"। যদি এটি ভুল হয় ... আপনার জানা ম্যাচের তালিকায় এটি যুক্ত করা উচিত যা আপনি সঠিক নন, তাই আপনি এটি আবার অনুমান করবেন না (হয় ক্রমান্বয়ে বা পৃথক অনুমান হিসাবে)।
dberm22

এর অর্থ এটি সম্ভাবনার তালিকা থেকে মুছে ফেলা; আমার কাছে সম্ভাব্যগুলির একটি তালিকা রয়েছে যা অসম্ভবগুলির একটি তালিকা নয়। ওহ, এবং আমি উল্লেখ করতে ভুলে গেছি যে এটি পুরুষের অ্যারে এবং মহিলা সংখ্যা 0-9 (বা বিপরীতে) হওয়ার অবস্থান রয়েছে। যদি আমি আরও গুরুতর জমা দিয়ে থাকতাম তবে আমি এ 5 বি 2 ইত্যাদি ফর্ম্যাটটি ব্যবহার করব।
কেইন

3

দ্রুত মাল্টি-থ্রেডেড সি ++ সংস্করণ

আমি জানি যে এই থ্রেডটি সক্রিয় হওয়ার পরে বেশ কিছুক্ষণ হয়ে গেছে, তবে আমার ভাগ করে নেওয়ার জন্য একটি দুর্দান্ত সংযোজন রয়েছে: আপনি কি সেই একের জন্য মিনিম্যাক্স অ্যালগরিদমের একটি সি ++ বাস্তবায়ন ? যা প্রতিটি সম্ভাব্য অনুমানের মূল্যায়নের গতি বাড়ানোর জন্য মাল্টি-থ্রেডিং ব্যবহার করে।

এই সংস্করণটি অনেক দ্রুত পাইথন সংস্করণের তুলনায় (100x সময়ের থেকে দ্রুত যখন মূল পাইথন সংস্করণ সর্বাধিক সেট আছে RANDOM_THRESHOLDএবং CLEVER_THRESHOLD)। এটি কোনও এলোমেলো অনুমান ব্যবহার করে না, বরং সমস্ত অনুমানের মূল্যায়ন করে এবং জমা দেওয়া অনুমান করে যে অনুমানটি সম্ভাব্য সমাধানের সর্বাধিক সংখ্যক (যেটি সবচেয়ে খারাপ প্রতিক্রিয়া দেখায়) সরিয়ে দেয় gu

ছোট গেমসের জন্য, "আয়টো-এন" কল করা সমস্ত গেমটি চালাবে! সম্ভাব্য লুকানো ম্যাচিং, এবং আপনাকে ফলাফলগুলির একটি সংক্ষিপ্তসার দেবে।

যেহেতু এটি এখনও 10 টি মূল্যায়ন করতে অক্ষম! সম্ভাব্য লুকানো ম্যাচিং, যদি আপনি "আইটো 10" কল করেন, উদাহরণস্বরূপ, সিমুলেটরটি তার নির্ধারিত প্রথম তিনটি অনুমান করে, তারপরে অনুমানটি বেছে নিতে মিনিম্যাক্স চালায় এবং ধরে নেওয়া হয় যে এটি সবচেয়ে খারাপ ক্ষেত্রে মূল্যায়ন দেওয়া হয়েছিল। এটি আমাদেরকে একটি "সবচেয়ে খারাপ অবস্থার পথ" একটি লুকানো ভেক্টরের দিকে নিয়ে যায় যা সম্ভবতঃ ভেক্টরদের শ্রেণিতে থাকে যা আলগোরিদমকে চিহ্নিত করতে সর্বাধিক সংখ্যক অনুমান করে। এই অনুমান পরীক্ষা করা হয়নি।

পর্যন্ত এন = 9 , একটি সিমুলেশন যে বেশী নিয়েছে হয়েছে না এন সমাধান করতে পালাক্রমে।

এটি নিজে পরীক্ষা করার জন্য উদাহরণ সংকলনটি নিম্নলিখিত হবে:

g++ -std=c++11 -lpthread -o ayto ayto.cpp

আউটপুট সহ এখানে একটি ছোট উদাহরণ:

$ ./ayto -4
Found (0, 1, 2, 3) in 2 guesses.
Found (0, 1, 3, 2) in 3 guesses.
Found (0, 2, 1, 3) in 2 guesses.
Found (0, 2, 3, 1) in 3 guesses.
Found (0, 3, 1, 2) in 2 guesses.
Found (0, 3, 2, 1) in 2 guesses.
Found (1, 0, 2, 3) in 1 guesses.
Found (1, 0, 3, 2) in 3 guesses.
Found (1, 2, 0, 3) in 3 guesses.
Found (1, 2, 3, 0) in 3 guesses.
Found (1, 3, 0, 2) in 3 guesses.
Found (1, 3, 2, 0) in 3 guesses.
Found (2, 0, 1, 3) in 3 guesses.
Found (2, 0, 3, 1) in 3 guesses.
Found (2, 1, 0, 3) in 3 guesses.
Found (2, 1, 3, 0) in 3 guesses.
Found (2, 3, 0, 1) in 3 guesses.
Found (2, 3, 1, 0) in 3 guesses.
Found (3, 0, 1, 2) in 3 guesses.
Found (3, 0, 2, 1) in 3 guesses.
Found (3, 1, 0, 2) in 3 guesses.
Found (3, 1, 2, 0) in 3 guesses.
Found (3, 2, 0, 1) in 3 guesses.
Found (3, 2, 1, 0) in 3 guesses.
***** SUMMARY *****
Avg. Turns: 2.75
Worst Hidden Vector: (0, 1, 3, 2) in 3 turns.

কোড

/* Multithreaded Mini-max Solver for MTV's Are You The One? */

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <cmath>

#define TEN_FACT (3628800)
#define NUM_CHUNKS (8)

using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::string;
using std::map;
using std::pair;
using std::find;
using std::abs;
using std::atoi;
using std::next_permutation;
using std::max_element;
using std::accumulate;
using std::reverse;
using std::thread;

struct args {
    vector<string> *perms;
    vector<string> *chunk;
    pair<string, int> *cd;
    int thread_id;
};

void simulate_game(const string &hidden, map<string, int> &turns_taken,
                   bool running_all);
bool picmp(const pair<string, int> &p1, const pair<string, int> &p2);
double map_avg(const map<string, int> &mp);
int nrand(int n);
int evaluate(const string &sol, const string &query);
vector<string> remove_perms(vector<string> &perms, int eval, string &query);
pair<string, int> guess_tb(vector<string> &perms, vector<string> &guessed_tb, int turn);
pair<string, int> guess_pm(vector<string> &perms, vector<string> &guessed, int turn);
void make_chunks(vector<string> &orig, vector<vector<string> > &chunks, int n);
string min_candidate(pair<string, int> *candidates, int n);
void get_score(struct args *args);
int wc_response(string &guess, vector<string> &perms);
bool prcmp(pair<int, int> x, pair<int, int> y);
void sequence_print(string s);
struct args **create_args(vector<string> &perms, pair<string, int> *cd, vector<string> &chunk, int thread_id);


vector<string> ORIGPERMS;

int main(int argc, char **argv)
{
    int sz;
    map<string, int> turns_taken;
    const string digits = "0123456789";
    bool running_all = false;

    if (argc != 2) {
        cout << "usage: 'ayto npairs'" << endl;
        return 1;
    } else {
        if ((sz = atoi(argv[1])) < 0) {
            sz = -sz;
            running_all = true;
        }
        if (sz < 3 || sz > 10) {
            cout << "usage: 'ayto npairs' where 3 <= npairs <= 10" << endl;;
            return 1;
        }
    }

    // initialize ORIGPERMS and possible_perms
    string range = digits.substr(0, sz);
    do {
        ORIGPERMS.push_back(range);
    } while (next_permutation(range.begin(), range.end()));

    if (running_all) {
        for (vector<string>::const_iterator it = ORIGPERMS.begin();
             it != ORIGPERMS.end(); ++it) {
            simulate_game(*it, turns_taken, running_all);
        }
        cout << "***** SUMMARY *****\n";
        cout << "Avg. Turns: " << map_avg(turns_taken) << endl;
        pair<string, int> wc = *max_element(turns_taken.begin(),
                                            turns_taken.end(), picmp);
        cout << "Worst Hidden Vector: ";
        sequence_print(wc.first);
        cout << " in " << wc.second << " turns." << endl;
    } else {
        string hidden = ORIGPERMS[nrand(ORIGPERMS.size())];
        simulate_game(hidden, turns_taken, running_all);
    }

    return 0;
}

// simulate_game:  run a single round of AYTO on hidden vector
void simulate_game(const string &hidden, map<string, int> &turns_taken,
                   bool running_all)
{
    vector<string> possible_perms = ORIGPERMS;
    pair<string, int> tbguess;
    pair<string, int> pmguess;
    vector<string> guessed;
    vector<string> guessed_tb;
    int e;
    int sz = hidden.size();

    if (!running_all) {
        cout << "Running AYTO Simulator on Hidden Vector: ";
        sequence_print(hidden);
        cout << endl;
    }

    for (int turn = 1; ; ++turn) {
        // stage one: truth booth
        if (!running_all) {
            cout << "**** Round " << turn << "A ****" << endl;
            cout << "Num. Possibilities: " << possible_perms.size() << endl;
        }
        tbguess = guess_tb(possible_perms, guessed_tb, turn);
        if (!running_all) {
            cout << "Guess: ";
            sequence_print(tbguess.first);
            cout << endl;
            e = tbguess.second;
            cout << "Worst-Case Evaluation: " << e << endl;
        } else {
            e = evaluate(hidden, tbguess.first);
        }
        possible_perms = remove_perms(possible_perms, e, tbguess.first);

        // stage two: perfect matching
        if (!running_all) {
            cout << "Round " << turn << "B" << endl;
            cout << "Num. Possibilities: " << possible_perms.size() << endl;
        }
        pmguess = guess_pm(possible_perms, guessed, turn);

        if (!running_all) {
            cout << "Guess: ";
            sequence_print(pmguess.first);
            cout << endl;
            e = pmguess.second;
            cout << "Worst-Case Evaluation: " << e << endl;
        } else {
            e = evaluate(hidden, pmguess.first);
        }
        if (e == sz) {
            cout << "Found ";
            sequence_print(pmguess.first);
            cout << " in " << turn << " guesses." << endl;
            turns_taken[pmguess.first] = turn;
            break;
        }

        possible_perms = remove_perms(possible_perms, e, pmguess.first);
    }
}

// map_avg:  returns average int component of a map<string, int> type
double map_avg(const map<string, int> &mp)
{
    double sum = 0.0;

    for (map<string, int>::const_iterator it = mp.begin(); 
         it != mp.end(); ++it) {
        sum += it->second;
    }

    return sum / mp.size();
}

// picmp:  comparison function for pair<string, int> types, via int component
bool picmp(const pair<string, int> &p1, const pair<string, int> &p2)
{
    return p1.second < p2.second;
}

// nrand:  random integer in range [0, n)
int nrand(int n)
{
    srand(time(NULL));

    return rand() % n;
}

// evaluate:  number of black hits from permutation or truth booth query
int evaluate(const string &sol, const string &query)
{
    int hits = 0;

    if (sol.size() == query.size()) {
        // permutation query
        int s = sol.size();
        for (int i = 0; i < s; i++) {
            if (sol[i] == query[i])
                ++hits;
        }
    } else {
        // truth booth query
        if (sol[atoi(query.substr(0, 1).c_str())] == query[1])
            ++hits;
    }

    return hits;
}

// remove_perms:  remove solutions that are no longer possible after an eval
vector<string> remove_perms(vector<string> &perms, int eval, string &query)
{
    vector<string> new_perms;

    for (vector<string>::iterator i = perms.begin(); i != perms.end(); i++) {
        if (evaluate(*i, query) == eval) {
            new_perms.push_back(*i);
        }
    }

    return new_perms;
}

// guess_tb:  guesses best pair (pos, val) to go to the truth booth
pair<string, int> guess_tb(vector<string> &possible_perms,
                           vector<string> &guessed_tb, int turn)
{
    static const string digits = "0123456789";
    int n = possible_perms[0].size();
    pair<string, int> next_guess;

    if (turn == 1) {
        next_guess.first = "00";
        next_guess.second = 0;
    } else if (possible_perms.size() == 1) {
        next_guess.first = "0" + possible_perms[0].substr(0, 1);
        next_guess.second = 1;
    } else {
        map<string, double> pair_to_count;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                pair_to_count[digits.substr(i, 1) + digits.substr(j, 1)] = 0;
            }
        }

        // count up the occurrences of each pair in the possible perms
        for (vector<string>::iterator p = possible_perms.begin();
             p != possible_perms.end(); p++) {
            int len = possible_perms[0].size();
            for (int i = 0; i < len; i++) {
                pair_to_count[digits.substr(i, 1) + (*p).substr(i, 1)] += 1;
            }
        }

        double best_dist = 1;
        int perm_cnt = possible_perms.size();
        for (map<string, double>::iterator i = pair_to_count.begin();
             i != pair_to_count.end(); i++) {
            if (find(guessed_tb.begin(), guessed_tb.end(), i->first)
                == guessed_tb.end()) {
                // hasn't been guessed yet
                if (abs(i->second/perm_cnt - .5) < best_dist) {
                    next_guess.first = i->first;
                    best_dist = abs(i->second/perm_cnt - .5);
                    if (i->second / perm_cnt < 0.5) // occurs in < half perms
                        next_guess.second = 0;
                    else                            // occurs in >= half perms
                        next_guess.second = 1;
                }
            }
        }
    }

    guessed_tb.push_back(next_guess.first);

    return next_guess;
}

// guess_pm:  guess a full permutation using minimax
pair<string, int> guess_pm(vector<string> &possible_perms,
                           vector<string> &guessed, int turn)
{
    static const string digits = "0123456789";
    pair<string, int> next_guess;
    vector<vector<string> > chunks;
    int sz = possible_perms[0].size();

    // on first turn, we guess "0, 1, ..., n-1" if truth booth was correct
    // or "1, 0, ..., n-1" if truth booth was incorrect
    if (turn == 1) {
        int fact, i;
        for (i = 2, fact = 1; i <= sz; fact *= i++)
            ;
        if (possible_perms.size() == fact) {
            next_guess.first = digits.substr(0, sz);
            next_guess.second = 1;
        } else {
            next_guess.first = "10" + digits.substr(2, sz - 2);
            next_guess.second = 1;
        }
    } else if (possible_perms.size() == 1) {
        next_guess.first = possible_perms[0];
        next_guess.second = possible_perms[0].size();
    } else {
        // run multi-threaded minimax to get next guess
        pair<string, int> candidates[NUM_CHUNKS];
        vector<thread> jobs;
        make_chunks(ORIGPERMS, chunks, NUM_CHUNKS);
        struct args **args = create_args(possible_perms, candidates, chunks[0], 0);

        for (int j = 0; j < NUM_CHUNKS; j++) {
            args[j]->chunk = &(chunks[j]);
            args[j]->thread_id = j;
            jobs.push_back(thread(get_score, args[j]));
        }
        for (int j = 0; j < NUM_CHUNKS; j++) {
            jobs[j].join();
        }

        next_guess.first = min_candidate(candidates, NUM_CHUNKS);
        next_guess.second = wc_response(next_guess.first, possible_perms);

        for (int j = 0; j < NUM_CHUNKS; j++)
            free(args[j]);
        free(args);
    }

    guessed.push_back(next_guess.first);

    return next_guess;
}

struct args **create_args(vector<string> &perms, pair<string, int> *cd, vector<string> &chunk, int thread_id)
{
    struct args **args = (struct args **) malloc(sizeof(struct args*)*NUM_CHUNKS);
    assert(args);
    for (int i = 0; i < NUM_CHUNKS; i++) {
        args[i] = (struct args *) malloc(sizeof(struct args));
        assert(args[i]);
        args[i]->perms = &perms;
        args[i]->cd = cd;
    }

    return args;
}

// make_chunks:  return pointers to n (nearly) equally sized vectors
//                from the original vector
void make_chunks(vector<string> &orig, vector<vector<string> > &chunks, int n)
{
    int sz = orig.size();
    int chunk_sz = sz / n;
    int n_with_extra = sz % n;
    vector<string>::iterator b = orig.begin();
    vector<string>::iterator e;

    for (int i = 0; i < n; i++) {
        int m = chunk_sz;    // size of this chunk
        if (n_with_extra) {
            ++m;
            --n_with_extra;
        }
        e = b + m;
        vector<string> subvec(b, e);
        chunks.push_back(subvec);
        b = e;
    }
}

// min_candidate:  string with min int from array of pair<string, ints>
string min_candidate(pair<string, int> *candidates, int n)
{
    int i, minsofar;
    string minstring;

    minstring = candidates[0].first;
    minsofar = candidates[0].second;
    for (i = 1; i < n; ++i) {
        if (candidates[i].second < minsofar) {
            minsofar = candidates[i].second;
            minstring = candidates[i].first;
        }
    }

    return minstring;
}

// get_score:  find the maximum number of remaining solutions over all
//             possible responses to the query s
//             this version takes a chunk and finds the guess with lowest score
//             from that chunk
void get_score(struct args *args)
{
    // parse the args struct
    vector<string> &chunk = *(args->chunk);
    vector<string> &perms = *(args->perms);
    pair<string, int> *cd = args->cd;
    int thread_id = args->thread_id;

    typedef vector<string>::const_iterator vec_iter;
    int sz = perms[0].size();

    pair<string, int> best_guess;
    best_guess.second = perms.size();
    int wc_num_remaining;
    for (vec_iter s = chunk.begin(); s != chunk.end(); ++s) {
        vector<int> matches(sz + 1, 0);
        for (vec_iter p = perms.begin(); p != perms.end(); ++p) {
            ++matches[evaluate(*s, *p)];
        }
        wc_num_remaining = *max_element(matches.begin(), matches.end());
        if (wc_num_remaining < best_guess.second) {
            best_guess.first = *s;
            best_guess.second = wc_num_remaining;
        }
    }

    cd[thread_id] = best_guess;

    return;
}

// wc_response:  the response to guess that eliminates the least solutions
int wc_response(string &guess, vector<string> &perms)
{
    map<int, int> matches_eval;

    for (vector<string>::iterator it = perms.begin(); it!=perms.end(); ++it) {
        ++matches_eval[evaluate(guess, *it)];
    }

    return max_element(matches_eval.begin(), matches_eval.end(), prcmp)->first;
}

// prcmp:  comparison function for pair<int, int> types in map
bool prcmp(pair<int, int> x, pair<int, int> y)
{
    return x.second < y.second;
}

void sequence_print(const string s)
{
    for (string::const_iterator i = s.begin(); i != s.end(); i++) {
        if (i == s.begin())
            cout << "(";
        cout << *i;
        if (i != s.end() - 1)
            cout << ", ";
        else
            cout << ")";
    }
}

আমি এটিকে তুমি কী একে স্থানান্তরিত করেছি ? আপডেট, দ্রুত কোড সহ গিটহাবে on
ক্রিস চুটে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.