চম্পের সর্বোত্তম প্রারম্ভিক পদক্ষেপটি সন্ধান করুন


14

চম্প একটি টু-প্লেয়ারের খেলা যা টুকরো টুকরো করে একটি আয়তক্ষেত্র সেটআপ করে। প্রতিটি খেলোয়াড় কোনও টুকরো অপসারণ করে তার উপরের সমস্ত টুকরা এবং ডানদিকে সরিয়ে নেয়। যে নীচে বাম টুকরা নেয় সে হারায়। এটি মোটামুটি সহজে প্রমাণিত হতে পারে যে প্রথম খেলোয়াড়ের সর্বদা একটি বিজয়ী পদক্ষেপ থাকে (1-বাই -1 আয়তক্ষেত্র বাদে); খুজেন.

  1. ইনপুটটি আয়তক্ষেত্রের মাত্রা (দুটি সংখ্যা)
  2. আউটপুট হল বিজয়ী পদক্ষেপের অবস্থান (দুটি সংখ্যা)
  3. যদি একের অধিক বিজয়ী পদক্ষেপ থাকে তবে আপনি এগুলির যে কোনওটিকে আউটপুট করতে পারেন।

এটি কোড গল্ফ; সংক্ষিপ্ততম কোড (যে কোনও ভাষা) জিতেছে।

উদাহরণ

দ্রষ্টব্য: আউটপুটগুলি কেবল দুটি সংখ্যা; নীচের ASCII শিল্পটি সংখ্যাটি কী বোঝায় তা প্রদর্শন করার জন্য।

ইনপুট: 5 3 (সূচকগুলি 1-ভিত্তিক নীচে-বাম কোণ থেকে শুরু)

আউটপুট: 4 3

XXX--
XXXXX
XXXXX

ইনপুট: 4 4

আউটপুট: 2 2

X---
X---
X---
XXXX

বোনাস

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


আপনার প্রথম উদাহরণে, আমি মনে করি যে আপনার কাছে একটি খুব বেশি ড্যাশ রয়েছে
kitcar2000

@ কিটকার আপনি ঠিক বলেছেন; স্থির করেছি।
Ypnypn

আমি আউটপুট ফর্ম্যাট বুঝতে পারি না। এই সংখ্যাগুলি এই পদের সাথে কীভাবে মিলবে?
আন্ডারগ্রাউন্ডোমোনাইল

নীচে বাম দিক থেকে @undermonmonil 1-ভিত্তিক সূচক। প্রথম সূচকটি অনুভূমিক অক্ষ এবং দ্বিতীয় সূচকটি উল্লম্ব সূচক।
মার্টিন ইন্ডার

2
আপনার অনুগ্রহের প্রতিক্রিয়ায়: দাবাতে, আপনার যে কোনও সময়ে 119 টিরও কম চলন চলনযোগ্য (সাধারণত অনেক কম) এবং আজ অবধি কোনও সুপার কম্পিউটার কম্পিউটার সর্বাধিক পরিচিত অ্যালগরিদম ব্যবহার করে দাবা সমাধানের কাছাকাছি আসতে পারেনি। 10 বাই 10 চম্প গ্রিডে প্রথম 100 টি সম্ভাবনা রয়েছে এবং তাদের প্রত্যেকেরই 1-99 সম্ভাব্য দ্বিতীয় চাল রয়েছে। আপনি কী ভাবেন যে শক্তিশালী করা সহজ হবে? আপনি যদি শক্ত জোর উত্তর চান তবে আমি আপনার গ্রিডের আকার সীমাবদ্ধ করার পরামর্শ দিচ্ছি। সম্পাদনা: তবে তা করবেন না। মাঝের প্রতিযোগিতাটি প্রয়োজনীয় পরিবর্তনগুলি খারাপ।
রেইনবোল্ট

উত্তর:


7

গল্ফস্ক্রিপ্ট, 82 ( 108 97 টি অক্ষর - 15 বোনাস)

~),1/{{:F$0=),{F\+}/}%}@(*(0*\{1${1$\{\(@<},=},{1$\{\(@>},+(-!},:Y!{.,/+0}*;}/;Y{.-1=.@?)' '@)n}/

যেহেতু আমি কোনও হিউরিস্টিকের জন্য জানতাম না এই দ্রবণটি সমাধানের জায়গার উপরে একটি সম্পূর্ণ অনুসন্ধান করে per আপনি অনলাইন চেষ্টা করতে পারেন । যদিও বাস্তবায়নটি অত্যন্ত দক্ষ তবে অনুসন্ধানের স্থানটি ইনপুট বাড়ানোর সাথে খুব দ্রুত বৃদ্ধি পায়।

উদাহরণ:

> 5 3
4 3

> 5 4
3 3

> 6 6
2 2

উপরে উল্লিখিত হিসাবে প্রয়োগটি পুনরাবৃত্তির উপর নির্ভর করে না তবে অনুসন্ধান স্পেসের প্রতিটি নোডটি একবারে একবার ঘুরে দেখেছে। নীচে আপনি কোডটির একটি বর্ণিত সংস্করণ পাবেন যা বিল্ডিং ব্লকগুলিকে আরও বিশদে বিশদ বর্ণনা করে।

আকারের একক বোর্ডের প্রতিনিধিত্ব ডাব্লু * এইচ থেকে 0 এর পরিসরে ডাব্লু সংখ্যার একটি তালিকা দিয়ে দেওয়া হয় h । প্রতিটি সংখ্যা সংশ্লিষ্ট কলামে টুকরো পরিমাণ দেয়। সুতরাং, একটি বৈধ কনফিগারেশন হ'ল একটি তালিকা যেখানে সংখ্যাগুলি শুরু থেকে শেষ অবধি বৃদ্ধি পাচ্ছে না (যে কোনও পদক্ষেপের সাথে আপনি নিশ্চিত হন যে ডানদিকে সমস্ত কলামগুলি নির্বাচিতটির চেয়ে সর্বাধিক উচ্চতর)।

~                   # Evaluate the input (stack is now w h)

# BUILDING THE COMPLETE STATE SPACE
# Iteratively builds the states starting with 1xh board, then 2xh board, ...

),1/                # Generate the array [[0] [1] ... [h]] which is the space for 1xh
{                   # This loop is now ran w-1 times and each run adds all states for the 
                    # board with one additional column
  {                 # The {}/] block simply runs for each of the existing states
    :F$0=           #   Take the smallest entry (which has to be the last one)
    ),              #   For the last column all values 0..x are possible
    {F\+}/          #     Append each of these values to the smaller state
  }%
}@(*

# The order ensures that the less occupied boards are first in the list.
# Thus each game runs from the end of the list (where [h h ... h] is) to 
# the start (where [0 0 ... 0] is located).

# RUN THROUGH THE SEARCH SPACE
# The search algorithm therefore starts with the empty board and works through all
# possible states by simply looping over this list. It builds a list of those states
# which are known as non-winning states, i.e. those states where a player should 
# aim to end after the move

(                   # Skips the empty board (which is a winning configuration)
0*\                 # and makes an empty list out of it (which will be the list of
                    # known non-winning states (initially empty))
{                   # Loop over all possible states
  1$                #   Copy of the list of non-winning states
  {                 #   Filter those which are not reachable from the current state,
                    #   because at least one column has more pieces that the current
                    #   board has
    1$\{\(@<},=
  },
  {                 #   Filter those which are not reachable from the current state,
                    #   because no valid move exists
    1$\{\(@>},+     #     Filter those columns which are different between start and
                    #     end state
    (-!             #     If those columns are all of same height it is possible to move
  },
  :Y                #   Assign the result (list of all non-winning states which are
                    #   reachable from the current configuration within one move)
                    #   to variable Y

  !{                #   If Y is non-empty this one is a winning move, otherwise 
                    #   add it to the list
    .,/+
    0               #     Push dummy value
  }*;
}/
;                   # Discard the list (interesting data was saved to variable Y)

# OUTPUT LOOP
# Since the states were ordered the last one was the starting state. The list of 
# non-winning states were saved to variable Y each time, thus the winning moves 
# from the initial configuration is contained in this variable.

Y{                  # For each item in Y
  .-1=.@?)          #   Get the index (1-based) of the first non-h value
  ' '               #   Append a space
  @)                #   Get the non-h value itself (plus one)
  n                 #   Append a newline
}/

সমাধানটি নিজেই এবং খুব সুন্দরভাবে মন্তব্য করা কোডের জন্য
Xuntar

উপরে-ডাউনের চেয়ে নীচে ডায়নামিক প্রোগ্রামিং। খুশী হলাম। আমি এটি করার বিষয়টি বিবেচনা করেছি, তবে নীচের অংশের ট্র্যাভারসালের জন্য বৈধ ক্রমে রাজ্যগুলি তৈরি করা পুনরাবৃত্ত অনুসন্ধানের চেয়ে আরও বেশি কাজ এবং বিভ্রান্তিকর ছিল। আমি অবাক হয়েছি এতক্ষণ কোডটি শেষ হয়েছিল; আমি গল্ফস্ক্রিপ্টের মতো নিবিড় ভাষাটি আরও সংক্ষিপ্ত সমাধান তৈরি করতে পেরেছিলাম বলে আশা করি।
ব্যবহারকারী 2357112

খুব সুন্দর এবং ভালভাবে চিন্তাভাবনা করেছেন
মউক

8

পাইথন 2 3, 141-15 = 126

def win(x,y):w([y]*x)
w=lambda b,f=print:not[f(r+1,c+1)for r,p in enumerate(b)for c in range(p)if(r+c)*w(b[:r]+[min(i,c)for i in b[r:]],max)]

ব্রুট-ফোর্স মিনিম্যাক্স অনুসন্ধান। প্রতিটি সম্ভাব্য পদক্ষেপের জন্য, আমরা পুনরাবৃত্তি করে দেখতে পারি যে আমরা সেই পদক্ষেপ নেওয়ার পরে প্রতিপক্ষ জিততে পারে কিনা। বেশ দুর্বলভাবে গল্ফড; অন্য কারও আরও ভাল করতে সক্ষম হওয়া উচিত। এটি এপিএলের একটি কাজের মতো অনুভব করে।

  • winপাবলিক ইন্টারফেস। এটি বোর্ডের মাত্রা নেয়, এটিকে বোর্ডের উপস্থাপনায় রূপান্তরিত করে এবং এটিকে পাস করে w
  • wমিনিম্যাক্স অ্যালগরিদম। এটি বোর্ডের স্থিতি নেয়, সমস্ত পদক্ষেপের চেষ্টা করে, একটি তালিকা তৈরি করে যার উপাদানগুলি বিজয়ী চলনের সাথে সামঞ্জস্য করে এবং তালিকাটি খালি থাকলে সত্যটি ফেরত দেয়। ডিফল্ট হিসাবে f=print, তালিকা তৈরির বিজয়ী পদক্ষেপ মুদ্রণের একটি পার্শ্ব প্রতিক্রিয়া রয়েছে। বিজয়ী পদক্ষেপের একটি তালিকা ফিরে এলে ফাংশনটির নামটি আরও বোধগম্য হতে ব্যবহৃত হত, তবে তারপরে আমি notস্থানটি বাঁচাতে তালিকার সামনে সরিয়ে নিয়েছি ।
  • for r,p in enumerate(b)for c in xrange(p) if(r+c): সমস্ত সম্ভাব্য পদক্ষেপের উপর Iterate। 1 1কিছুটা বেস কেসকে সরল করে আইনী পদক্ষেপ হিসাবে বিবেচনা করা হয় না।
  • b[:r]+[min(i,c)for i in b[r:]]: স্থানাঙ্ক rএবং প্রতিনিধিত্বকারী পদক্ষেপের পরে বোর্ডের অবস্থা তৈরি করুন c
  • w(b[:r]+[min(i,c)for i in b[r:]],max): নতুন রাষ্ট্রটি একটি হারানো রাষ্ট্র কিনা তা দেখার জন্য পুনরাবৃত্তি করুন। maxসবচেয়ে সংক্ষিপ্ত ফাংশনটি আমি খুঁজে পেতে পারি যে এটি দুটি পূর্ণসংখ্যার যুক্তি গ্রহণ করবে এবং অভিযোগ করবে না।
  • f(r+1,c+1): fমুদ্রিত হলে মুভটি মুদ্রণ করে। যাই হোক না কেন f, এটি তালিকা দৈর্ঘ্যের প্যাড করার জন্য একটি মান উত্পাদন করে।
  • not [...]: খালি তালিকার জন্য এবং অকার্যকর জন্য notফেরত ।TrueFalse

মূল পাইথন 2 কোড, সম্পূর্ণরূপে নিরবচ্ছিন্ন, অনেক বড় ইনপুটগুলি পরিচালনা করতে মেমোয়েজেশন সহ:

def win(x, y):
    for row, column in _win(Board([y]*x)):
        print row+1, column+1

class MemoDict(dict):
    def __init__(self, func):
        self.memofunc = func
    def __missing__(self, key):
        self[key] = retval = self.memofunc(key)
        return retval

def memoize(func):
    return MemoDict(func).__getitem__

def _normalize(state):
    state = tuple(state)
    if 0 in state:
        state = state[:state.index(0)]
    return state

class Board(object):
    def __init__(self, state):
        self.state = _normalize(state)
    def __eq__(self, other):
        if not isinstance(other, Board):
            return NotImplemented
        return self.state == other.state
    def __hash__(self):
        return hash(self.state)
    def after(self, move):
        row, column = move
        newstate = list(self.state)
        for i in xrange(row, len(newstate)):
            newstate[i] = min(newstate[i], column)
        return Board(newstate)
    def moves(self):
        for row, pieces in enumerate(self.state):
            for column in xrange(pieces):
                if (row, column) != (0, 0):
                    yield row, column
    def lost(self):
        return self.state == (1,)

@memoize
def _win(board):
    return [move for move in board.moves() if not _win(board.after(move))]

ডেমো:

>>> for i in xrange(7, 11):
...     for j in xrange(7, 11):
...         print 'Dimensions: {} by {}'.format(i, j)
...         win(i, j)
...
Dimensions: 7 by 7
2 2
Dimensions: 7 by 8
3 3
Dimensions: 7 by 9
3 4
Dimensions: 7 by 10
2 3
Dimensions: 8 by 7
3 3
Dimensions: 8 by 8
2 2
Dimensions: 8 by 9
6 7
Dimensions: 8 by 10
4 9
5 6
Dimensions: 9 by 7
4 3
Dimensions: 9 by 8
7 6
Dimensions: 9 by 9
2 2
Dimensions: 9 by 10
7 8
9 5
Dimensions: 10 by 7
3 2
Dimensions: 10 by 8
6 5
9 4
Dimensions: 10 by 9
5 9
8 7
Dimensions: 10 by 10
2 2

জন্য 13x13নিতে 2x2এবং আপনি win চাই।
ডেভিডসপ্রো

@ ডেভিডসব্রো: হ্যাঁ, এটি 1x1 এর চেয়ে বড় কোনও স্কোয়ার বোর্ডের জন্য বিজয়ী পদক্ষেপ, তবে আমার কোডটি এখনও এটি গণনা করতে পারে নি।
ব্যবহারকারী 2357112

2

পার্ল 6: 113 108 টি অক্ষর - 15 = 93 পয়েন্ট

এই এক কঠিন ছিল! এখানে আনকচ করা সংস্করণটি দেওয়া হয়েছে যা প্রযুক্তিগতভাবে সঠিক তবে অ-তুচ্ছ ইনপুটগুলির জন্য খুব দীর্ঘ সময় লাগবে।

sub win(*@b){map ->\i,\j{$(i+1,j+1) if @b[i][j]&&!win @b[^i],@b[i..*].map({[.[^j]]})},(^@b X ^@b[0])[1..*]}

এটি ঠিক @ ইউজার 2357112 এর পাইথন বাস্তবায়নের মতো কাজ করে (তাকে উত্সাহিত করুন , আমি তার কাজটি ছাড়াই এটি বের করতে পারতাম না!) বিজয় () প্রস্থ এবং দৈর্ঘ্যের পরিবর্তে একটি শম্প বোর্ড (অ্যারে) নেয়। এটি এর মতো ব্যবহার করা যেতে পারে:

loop {
    my ($y, $x) = get.words;
    .say for @(win [1 xx $x] xx $y)
}

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

my %cache;
sub win (*@b) {
    %cache{
        join 2, map {($^e[$_]??1!!0 for ^@b[0]).join}, @b
    } //= map ->\i,\j{
        $(i+1,j+1) if @b[i][j] and not win
            @b[^i], @b[i..*].map({[.[^(* min j)]]}).grep: +*;
    },(^@b X ^@b[0])[1..*]
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.