लागू करें


11

पृष्ठभूमि

मेंस ( M achine E ducable N oughts A nd C rosses E ngine) 1960 के दशक में ब्रिटिश कंप्यूटर वैज्ञानिक डोनाल्ड मिक्सी द्वारा बनाए गए गेम नॉट्स एंड क्रॉस के लिए एक अल्पविकसित उथली मशीन लर्निंग एल्गोरिदम है। यह मूल रूप से 304 माचिस के साथ लागू किया गया था, प्रत्येक को एक बोर्ड की स्थिति और रंगीन मोतियों से युक्त (नौ रंगों में से एक, संभव चालों का प्रतिनिधित्व करते हुए) के साथ लेबल किया गया था। मिक्सी ने गणना की कि ये 304 माचिस बोर्ड पर चलने वाले हर संयोजन के लिए पर्याप्त थे।

आपके बीच और अधिक गणितीय यह महसूस कर सकता है कि एन एंड सी बोर्ड पर वास्तव में नॉट्स, क्रॉस और ब्लैंक्स के 19,683 संभावित संयोजन हैं; हालाँकि, उन्होंने इस संख्या में कटौती करने के तरीकों की गणना की (एल्गोरिथ्म को गति देने के लिए, और माचिस की तीली से कटने की संभावना)। सबसे पहले, उन्होंने सभी संभावित कदमों को हटा दिया, जैसे:

-------
|X|0|X|
| |0| |
|X|X| |
-------

(दो नॉटीज़ और चार क्रॉस)

इसके बाद, उन्होंने रोटेशन के लिए मुआवजा दिया। उदाहरण के लिए, यदि हम माचिस देखते हैं:

-------
| |0|0|
|X| |X|
| |0| |
-------

हम उसी बॉक्स का उपयोग कर सकते हैं

-------
| |X| |
|0| |0|
| |X|0|
-------

इसलिए, उपरोक्त रंग के मोती सापेक्ष स्थिति का प्रतिनिधित्व करते हैं, न कि निरपेक्ष। उदाहरण के लिए, अगर हमने कहा कि एक लाल मनका का मतलब शीर्ष-बाएँ है, तो हम बॉक्स के शीर्ष पर स्थित छवि को देखेंगे और देखेंगे:

-------
| |0|0|
|X| |X|
| |0| |
-------

तो हम जानते हैं कि इस मामले में यह बोर्ड है, तो लाल मनका का अर्थ होगा:

-------
|R|0|0|
|X| |X|
| |0| |
-------

लेकिन अगर यह बोर्ड है:

-------
| |X| |
|0| |0|
| |X|0|
-------

लाल मनका मतलब होगा

-------
| |X|R|
|0| |0|
| |X|0|
-------

इन परिवर्तनों ने घूर्णन और अकशेरुकी के लिए (सभी दिशाओं में, विकर्ण सहित) के लिए आवेदन किया। एक बार फिर, आपको केवल एक बार इस तरह से प्रत्येक माचिस को बचाने की आवश्यकता है: प्रत्येक परिवर्तन के लिए अलग-अलग वर्चुअल बॉक्स न बनाएं!

एक और सरलीकरण मिक्सी ने यह सुनिश्चित करने के लिए किया था कि कंप्यूटर पहले चला जाए। इस तरह, वह सभी प्रथम-स्तरीय चालों को हटा सकता है, शेष बचे हुए पांचवे हिस्से को हटा सकता है। अंत में, उन्होंने सभी गेम-एंडिंग बॉक्स को हटा दिया (क्योंकि इन चरणों पर आगे 'सामग्री' या चाल की आवश्यकता नहीं थी)।

अभी, एल्गोरिथ्म पर ही (यह बहुत सरल है):

  1. सबसे पहले, यह तय करें कि मोतियों के रंग क्या दर्शाते हैं। बोर्ड पर प्रत्येक स्थान का प्रतिनिधित्व करने के लिए आपको 9 रंगों की आवश्यकता होगी।
  2. खेल की शुरुआत में, 304 माचिस की प्रत्येक माला में मोती होते हैं। हालांकि मोतियों यादृच्छिक रंग के होते हैं (इसलिए डुप्लिकेट ठीक हैं), उन्हें संभव चालें होना चाहिए (इसलिए यदि बोर्ड राज्य की छवि मध्य-दाईं ओर 'O' दर्शाती है, तो आप उस बीड का उपयोग नहीं कर सकते हैं जो मध्य का प्रतिनिधित्व करता है- सही)।
  3. हर बार जब यह मेंस (एक्स) मोड़ होता है, तो उस पर छपे वर्तमान बोर्ड की स्थिति (या इसके कुछ परिवर्तन) के साथ माचिस खोजें।
  4. माचिस खोलें, और यादृच्छिक रूप से वहां कोई भी मनका चुनें।
  5. पता करें कि माचिस की डिब्बी पर चित्र को प्राप्त करने के लिए बोर्ड की स्थिति कैसे बदल दी गई है (उदाहरण के लिए 90 डीजी प्रतिस्वेदक घुमाया गया)। फिर, उस परिवर्तन को मनके पर लागू करें (जैसे शीर्ष-बाएँ बाएँ-बाएँ हो जाता है)।
  6. उस वर्ग में एक X रखें। माचिस से चयनित मनका निकालें। यदि बॉक्स को परिणामस्वरूप खाली छोड़ दिया जाता है, तो बॉक्स में तीन यादृच्छिक (संभव) मोतियों को डालें, और उनमें से एक को इस कदम के लिए चुनें।
  7. खेल खत्म होने तक 3-6 दोहराएं।
  8. अगर मेन्सक गेम जीत गया, तो हर माचिस के माध्यम से वापस जाएं। फिर, उस चाल पर किस रंग के मनके का उपयोग किया जाता है, इसे वापस ट्रेस करें। बॉक्स में मनके के उस रंग के दो रखो (ताकि मूल मनका + एक और हो, जिससे मेंस की संभावना बढ़ जाए जो अगली बार उस स्थिति में पहुंच जाए)
  9. यदि मेंस ने खेल को खो दिया, तो कुछ भी न करें ( मोतियों को प्रतिस्थापित न करें )।
  10. यदि मेंस ने खेल को आकर्षित किया है, तो उसके प्रत्येक चाल में उपयोग किए गए मनका को बदलें, लेकिन एक अतिरिक्त न जोड़ें, ताकि आप जो शुरू करते हैं उसके साथ छोड़ दें।

यह हमें एक एल्गोरिथ्म के साथ छोड़ देता है जो बहुत सरल है, लेकिन इसे लागू करना मुश्किल है। यह आपकी चुनौती का आधार बनता है।

यदि आप अभी भी भ्रमित हैं, तो http://chalkdustmagazine.com/features/menace-machine-educable-noughts-crosses-engine/ देखें - यह वही है जो मैंने तब पढ़ा जब मैंने पहली बार इस एल्गोरिथ्म के बारे में सीखा

चुनौती

कंप्यूटर के साथ टिक-टैक-टो का गेम खेलें। प्रत्येक चरण में, सभी माचिस की सामग्री का उत्पादन करें।

इनपुट

  • कार्यक्रम की शुरुआत में एक नंबर, जिसमें कहा गया था कि आप कितने गेम मेंस के खिलाफ खेलना चाहते हैं
  • फिर, मेंस की पहली बारी के बाद, आप अपनी चाल को दो वर्ण स्ट्रिंग के रूप में इनपुट करते हैं, पहला अक्षर "L", "R" या "M" (बाएं, दाएं या मध्य) Y अक्ष का संदर्भ देता है। फिर आप एक अन्य पत्र (फिर से, "एल", "आर", या "एम") इनपुट करते हैं, इस बार एक्स अक्ष का जिक्र करते हैं। सभी चाल और खेल के लिए दोहराएँ।

आउटपुट

  • प्रत्येक नए गेम की शुरुआत में, आउटपुट "नया गेम"।
  • खिलाड़ी द्वारा प्रत्येक चाल के बाद, बोर्ड को किसी भी उचित प्रारूप में आउटपुट करें। यह सुंदर दिखने की जरूरत नहीं है (जैसे बोर्ड के पदों का प्रतिनिधित्व करने वाले सरणियों की एक सरणी ठीक है)।
  • खिलाड़ी द्वारा प्रत्येक कदम के बाद, मेंस को एक कदम उठाना चाहिए। मेंस के कदम के बाद बोर्ड का आउटपुट
  • प्रत्येक गेम के बाद, सभी 304 माचिस की सामग्री का उत्पादन करें। बीड्स को एक अक्षर, एक रंग, चरित्र या जो भी स्ट्रिंग या पूर्णांक आपको पसंद है (कोई संकेत, अनाम फ़ंक्शन आदि) का प्रतिनिधित्व किया जा सकता है ।

नियम

  1. यह , इसलिए बाइट्स जीत में सबसे छोटा जवाब है।
  2. मेंस की प्रतिक्रिया को देखने के बाद मुझे इनपुट चालों में सक्षम होना चाहिए। कोई भी 'इस समारोह में अपने सभी चालें पास नहीं करता है, और देखो कि खेल कैसे खेलता है'।
  3. खेलों के बीच बोर्ड को मंजूरी देनी चाहिए।
  4. माचिस बॉक्स को गेम के बीच साफ नहीं किया जाना चाहिए (यह मशीन लर्निंग को रीसेट कर देगा)
  5. आपके पास 304 माचिस होनी चाहिए। कोई भी इस एल्गोरिथ्म को सभी 19,683 माचिस के साथ लागू कर सकता है, लेकिन सीखना धीमा है (क्योंकि इसमें उपयोगी सामग्री के साथ उन सभी को प्राप्त करने के लिए बहुत सारे गेम की आवश्यकता होती है )।
  6. आउटपुट किसी भी उचित प्रारूप में हो सकता है, और इनपुट पीपीसीजी मानकों के अनुसार लिया जा सकता है (जब तक यह नियम 2 का अनुपालन करता है)। यदि आपको इनपुट प्रारूप को समायोजित करने की आवश्यकता है (जैसा कि ' इनपुट ' अनुभाग में वर्णित है ) तो यह ठीक है जब तक यह समझ में आता है।
  7. एक गेम तब समाप्त होता है जब कोई खिलाड़ी जीतता है (तीन पंक्ति में तिरछे, क्षैतिज या लंबवत रूप से) या यदि कोई ड्रॉ होता है (बोर्ड भरा हुआ है और कोई विजेता नहीं है)
  8. जबकि मेंस को संभावित चालें बनाने की जरूरत होती है (और प्रत्येक माचिस के अंदर केवल संभव मोती होते हैं), चुनौती के लिए आपको उपयोगकर्ता के इनपुट को मान्य करने की आवश्यकता नहीं है। यदि वे कुछ गलत टाइप करते हैं, तो आपका प्रोग्राम जो कुछ भी कर सकता है (पूरी तरह से पागल हो, त्रुटि फेंक, आदि) - आप मान सकते हैं कि इनपुट सही है।

मुझे याद है कि मार्टिन गार्डनर ने सरल गेम हेक्सापोन का उपयोग करते हुए इस विचार का प्रदर्शन किया था, हालांकि मैं भूल जाता हूं कि उन्होंने उस "कंप्यूटर" का नाम दिया था जिसका उन्होंने निर्माण किया था।
नील



1
बड़ी चुनौती। त्वरित प्रश्नों के युगल: 1. एक बार एक बॉक्स में दिए गए स्थान में एक से अधिक मनका होने के बाद, आउटपुट में इसका प्रतिनिधित्व कैसे किया जाना चाहिए? 2. क्या आप वास्तव में प्रत्येक कदम के बाद सभी 304 बॉक्स (2736 सेल) आउटपुट चाहते हैं?
निक केनेडी

@NickKennedy प्रतिक्रिया के लिए धन्यवाद। जिस तरह से मैं उम्मीद करूंगा कि मोतियों का प्रतिनिधित्व करने पर यह एक सरणी के रूप में है (हालांकि आप इसे अलग-अलग भाषाओं को प्रतिबंधित नहीं करने के लिए अलग-अलग तरीके से कर सकते हैं), उदाहरण के लिए यदि आपने मोतियों का प्रतिनिधित्व करने के लिए संख्याएँ चुनीं [[0, 2, 6], [4, 8, 4, 3, 3], [7, 7, 7, 7, 7, 7, 7, 8], [1], ... [3, 3, 5, 4]]:।
गीज़ा केर्केसेनी

जवाबों:


3

आर , 839 बाइट्स

options(max.print=1e5)
s=colSums
r=rowSums
m=matrix
a=array
y=apply
S=sum
p=sample
b=m(rep(i<-1:(K=3^9),e=9)%/%(E=3^(8:0))%%3,c(9,K))
V=a(1:9,c(3,3,8))
V[,,2:4]=c(V[x<-3:1,,1],V[,x,1],V[x,x,1])
V[,,5:8]=y(V[,,1:4],3,t)
d=aperm(a(b[c(V),],c(9,8,K)),c(1,3,2))
v=m(V,9)
g=y(m(match(e<-y(d*E,2:3,S),i),,8),1,min)
g[K]=K
G=9-y(t(e==g)*8:1,2,max)
h=s(a(c(b,d[,,5],b[c(1,5,9,3,5,7,1:3),]),c(3,3,K,3))*3^(0:2))
k=r(s(h==13))>0
l=r(s(h==26))>0
o=s(b>0)
M=b
M[M==0]=-1
repeat{A=b[,t<-K]
z=j=c();B=1
repeat{if(S(pmax(-M[,t],0))<1)M[p(9,pmin(3,S(x)),,x<-M[,t]<1),t]=-1
z=c(z,u<-p(9,1,,pmax(-M[,t],0)))
j=c(j,t)
A[v[,G[B]][u]]=1
print(m(A,3))
if(k[B<-S(A*E)]||o[B]==9)break
A[ceiling((utf8ToInt(readline())-76)/5)%*%c(1,3)+1]=2
if(l[B<-S(A*E)])break
t=g[B]}
M[x]=M[x<-cbind(z,j)]-k[B]+l[B]
print(a(M[,g==seq(g)&!k&!l&s(b==1)==s(b==2)&o<8],c(3,3,304)))}

इसे ऑनलाइन आज़माएं!

काफी लंबा जवाब, लेकिन यह सीधी चुनौती नहीं थी। यहां TIO लिंक विफल हो जाएगा क्योंकि यह इंटरैक्टिव इनपुट की उम्मीद करता है। यहां एक ऐसा संस्करण है जो एक दूसरे, यादृच्छिक खिलाड़ी के खिलाफ खेलता है जो सिर्फ यादृच्छिक पर एक स्थान चुनता है। इस दूसरे संस्करण के लिए आउटपुट सिर्फ एक ड्रॉ के लिए विजेता (1, 2 या 0) है। सभी बोर्ड पदों के लिए माचिस की तीलियों का उपयोग किया जाता है, लेकिन इसका उपयोग केवल 304 प्रति युक्ति के लिए किया जाता है। वे प्रत्येक स्थिति में मोतियों की संख्या को इंगित करने के लिए ऋणात्मक संख्याओं वाले बोर्ड की प्रतियों के रूप में कार्यान्वित किए जाते हैं। मैंने मूल कल्पना के अनुसार वैक्टर की एक सूची के साथ प्रयोग किया, लेकिन यह कम सहज था।

यह टिप्पणियों के साथ एक कम गोल्फ वाला संस्करण है (लेकिन अभी भी छोटे चर नाम हैं)। ध्यान दें कि यह माचिस को प्रिंट नहीं करता है क्योंकि वे बहुत लंबे हैं। यह एक इंटरैक्टिव खिलाड़ी 2, एक यादृच्छिक खिलाड़ी 2 या खिलाड़ी 2 के लिए एक ही मैचबॉक्स रणनीति को लागू कर सकता है।

auto = 1 # 1 = Random player 2, 2 = Player 2 uses learning strategy
         # 0 for interactive
print_board <- function(board) {
  cat(apply(matrix(c(".", "X", "O")[board + 1], 3), 1, paste, collapse = ""), "", sep = "\n")
}
E = 3 ^ (8:0) # Number of possible arrangements of board
              # ignoring rotations etc.
# Make all possible boards
b = matrix(rep(1:3 ^ 9, e = 9) %/% E %% 3, c(9, 3 ^ 9))
# Define the eight possible rotation/inversion matrices
V = array(1:9, c(3, 3, 8))
V[, , 2:4] = c(V[x <- 3:1, , 1], V[, x, 1], V[x, x, 1])
V[, , 5:8] = apply(V[, , 1:4], 3, t)
# Create eight copies of the 19683 boards with each transformation
d = aperm(array(b[c(V), ], c(9, 8, 3 ^ 9)), c(1, 3, 2))
v = matrix(V, 9)
# Create reverse transformations (which are the same except for rotation)
w = v[, c(1:5, 7, 6, 8)]
# Find the sums of each transformation using base 3
e = apply(d * E, 2:3, sum)
# Find the lowest possible sum for each board's transformed versions
# This will be the one used for the matchboxes
f = matrix(match(e, 1:3 ^ 9), , 8)
g = apply(f, 1, min)
# Store which transformation was necessary to convert the lowest board
# into this one
G = 9 - apply(t(e == g) * 8:1, 2, max)
# Work out which boards have 3-in-a-row
h = colSums(array(c(b, d[, , 5], b[c(1, 5, 9, 3, 5, 7, 1:3), ]), c(3, 3, 3 ^ 9, 3)) * 3 ^ (0:2))
k = rowSums(colSums(h == 13)) > 0 # player 1 wins
l = rowSums(colSums(h == 26)) > 0 # player 2 wins
# Store how many cells are filled
o = colSums(b > 0)
# Create matchboxes. These contain the actual board configuration, but
# instead of zeroes for blanks have a minus number. This is initially -1,
# but will ultimately represent the number of beads for that spot on the
# board.
M = b
M[M == 0] = -1
repeat {
  # Initialise board and storage of moves and intermediate board positions
  A = b[, t <- 3 ^ 9]
  z = j = c()
  C = 1
  # If we're automating player 2 also, initialise its storage
  if (auto) {
    Z = J = c()
  }
  repeat {
    # If the current board's matchbox is empty, put up to three more beads
    # back in
    if (sum(pmax(-M[, t], 0)) == 0) {
      M[sample(9, pmin(3, sum(x)), , x <- M[, t] == 0), t] = -1
    }
    # Take out a bead from the matchbox
    u = sample(9, 1, , pmax(-M[, t], 0))
    # Mark the bead as taken out
    M[u, t] = M[u, t] + 1
    # Store the bead and board position in the chain for this game
    z = c(z, u)
    j = c(j, t)
    # Mark the spot on the board
    A[v[, C][u]] = 1
    # Print the board
    if (!auto) print_board(matrix(A, 3))
    # Check if  player 1 has won or board is full
    if (k[B <- sum(A * E)] || o[B] == 9) break
    if (auto) {
      # Repeat for player 2 if we're automating its moves
      # Note if auto == 1 then we pick at random
      # If auto == 2 we use the same algorithm as player 1
      D = g[B]
      if (sum(pmax(-M[, D], 0)) == 0) {
        M[sample(9, pmin(3, sum(x)), , x <- M[, D] == 0), D] = -1
      }
      U = sample(9, 1, , if (auto == 1) M[, D] <= 0 else pmax(-M[, D], 0))
      Z = c(Z, U)
      J = c(J, D)
      A[v[, G[B]][U]] = 2
    } else {
      cat(
        "Please enter move (LMR for top/middle/bottom row and\nLMR for left/middle/right column, e.g. MR:"
      )
      repeat {
        # Convert LMR into numbers
        q = ceiling((utf8ToInt(readline()) - 76) / 5)
        if (length(q) != 2)
          stop("Finished")
        if (all(q %in% 0:2) && A[q %*% c(1, 3) + 1] == 0) {
          break
        } else {
          message("Invalid input, please try again")
        }
      }
      A[q %*% c(1, 3) + 1] = 2
    }
    if (l[B <- sum(A * E)])
      break
    # Player 2 has won
    t = g[B]
    C = G[B]
  }
  if (auto) {
    cat(c("D", 1:2)[1 + k[B] + 2 * l[B]])
  } else {
    cat("Outcome:", c("Draw", sprintf("Player %d wins", 1:2))[1 + k[B] + 2 * l[B]], "\n")
  }
  # Add beads back to matchbox
  M[x] = M[x <- cbind(z, j)] - k[B] - 1 + l[B]
  if (auto)
    M[x] = M[x <- cbind(Z, J)] - l[B] - 1 + k[B]
}

बहुत चालाक! बेशक, घुमाव मुश्किल बना देते हैं, लेकिन बॉट खिलाड़ी को भी जोड़ने के लिए धन्यवाद!
गीज़ा केर्केसेनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.