सीजेएम, 189 187 बाइट्स
यह समझाने वाला कठिन है ... समय की जटिलता की गारंटी है O(scary)
।
qi:N_3>{,aN*]N({{:L;N,X)-e!{X)_@+L@@t}%{X2+<z{_fe=:(:+}%:+!},}%:+}fX{:G;N3m*{_~{G@==}:F~F\1m>~F\F=}%:*},:L,({LX=LX)>1$f{\_@a\a+Ne!\f{\:M;~{M\f=z}2*\Mff==}:|{;}|}\a+}fX]:~$e`{0=1=},,}{!!}?
यदि आप पर्याप्त बहादुर हैं, तो इसे ऑनलाइन आज़माएं । अपने भद्दे लैपटॉप पर मैं जावा दुभाषिया के साथ 6 तक या ऑनलाइन दुभाषिया में 5 प्राप्त कर सकता हूं।
व्याख्या
मेरे पास एक बड़ी गणित पृष्ठभूमि नहीं है (बस हाई स्कूल समाप्त होने के बाद, अगले सप्ताह यूनि में सीएस शुरू करना)। इसलिए मेरे साथ सहन करें अगर मैं गलतियाँ करता हूँ, तो स्पष्ट रूप से बताऊँ, या बहुत ही अक्षम तरीके से काम करता हूँ।
मेरा दृष्टिकोण एक क्रूर बल है, हालांकि मैंने इसे थोड़ा और अधिक चतुर बनाने की कोशिश की। मुख्य चरण हैं:
- सभी संभव ऑपरेंड उत्पन्न * आदेश के एक समूह के लिए n (यानी, आदेश के सभी समूहों की गणना n );
- आदेश एन के दो समूहों के बीच सभी संभावित जीवों bi उत्पन्न ;
- चरण 1 और 2 से परिणामों का उपयोग करते हुए, आदेश n के दो समूहों के बीच सभी समरूपता निर्धारित करें ;
- चरण 3 से परिणाम का उपयोग करते हुए, समरूपता तक समूहों की संख्या की गणना करें।
प्रत्येक चरण कैसे किया जाता है, यह देखने से पहले, आइए कुछ तुच्छ कोड प्राप्त करें:
qi:N_ e# Get input as integer, store in N, make a copy
3>{...} ? e# If N > 3, do... (see below)
{!!} e# Else, push !!N (0 if N=0, 1 otherwise)
निम्नलिखित एल्गोरिथ्म n <4 के साथ सही ढंग से काम नहीं करता है , 0 से 3 तक के मामलों को एक दोहरे नकार के साथ नियंत्रित किया जाता है।
अब से, एक समूह के तत्वों को {1, ए, बी, सी, ...} के रूप में लिखा जाएगा , जहां 1 पहचान तत्व है। सीजेएम कार्यान्वयन में, संबंधित तत्व {0, 1, 2, 3, ...} हैं , जहां 0 पहचान तत्व है।
आइए चरण 1 से शुरू करें। आदेश n के समूह के लिए सभी संभव ऑपरेटरों को लिखना सभी मान्य n × n केली टेबल बनाने के बराबर है । पहली पंक्ति और स्तंभ तुच्छ हैं: वे दोनों {1, ए, बी, सी, ...} (बाएं से दाएं, ऊपर-नीचे) हैं।
e# N is on the stack (duplicated before the if)
,a e# Generate first row [0 1 2 3 ...] and wrap it in a list
N* e# Repeat row N times (placeholders for next rows)
] e# Wrap everything in a list
e# First column will be taken care of later
यह जानते हुए कि केली तालिका एक कम लैटिन वर्ग (रद्दीकरण संपत्ति के कारण) संभव तालिकाओं को पंक्ति-दर-पंक्ति उत्पन्न करने की अनुमति देता है। दूसरी पंक्ति (इंडेक्स 1) से शुरू करते हुए, हम उस पंक्ति के लिए सभी अनूठे क्रमपरिवर्तन उत्पन्न करते हैं , जो पहले कॉलम को इंडेक्स के मान पर नियत रखते हैं।
N({ }fX e# For X in [0 ... N-2]:
{ }% e# For each table in the list:
:L; e# Assign the table to L and pop it off the stack
N, e# Push [0 ... N-1]
X) e# Push X+1
- e# Remove X+1 from [0 ... N-1]
e! e# Generate all the unique permutations of this list
{ }% e# For each permutation:
X)_ e# Push two copies of X+1
@+ e# Prepend X+1 to the permutation
L@@t e# Store the permutation at index X+1 in L
{...}, e# Filter permutations (see below)
:+ e# Concatenate the generated tables to the table list
उन सभी क्रमपरिवर्तन मान्य नहीं हैं, निश्चित रूप से: प्रत्येक पंक्ति और स्तंभ में सभी तत्व बिल्कुल एक बार होने चाहिए। इस उद्देश्य के लिए एक फ़िल्टर ब्लॉक का उपयोग किया जाता है (एक सत्य मूल्य क्रमचय रखता है, एक झूठा व्यक्ति इसे हटा देता है):
X2+ e# Push X+2
< e# Slice the permutations to the first X+2 rows
z e# Transpose rows and columns
{ }% e# For each column:
_fe= e# Count occurences of each element
:( e# Subtract 1 from counts
:+ e# Sum counts together
:+ e# Sum counts from all columns together
! e# Negate count sum:
e# if the sum is 0 (no duplicates) the permutation is kept
e# if the sum is not zero the permutation is filtered away
ध्यान दें कि मैं जेनरेशन लूप के अंदर फ़िल्टरिंग कर रहा हूं: यह कोड को अधिक लंबा बनाता है (विशिष्ट पीढ़ी और फ़िल्टरिंग की तुलना में), लेकिन प्रदर्शन में सुधार करता है। आकार n के एक सेट के क्रमपरिवर्तन की संख्या n है ! , इसलिए छोटे समाधान के लिए बहुत अधिक स्मृति और समय की आवश्यकता होगी।
वैध केली तालिकाओं की एक सूची ऑपरेटरों की गणना करने की दिशा में एक शानदार कदम है, लेकिन एक 2 डी संरचना होने के नाते, यह संबद्धता की जांच नहीं कर सकता है, जो एक 3 डी संपत्ति है। तो अगला कदम गैर-साहचर्य कार्यों को फ़िल्टर करना है।
{ }, e# For each table, keep table if result is true:
:G; e# Store table in G, pop it off the stack
N3m* e# Generate triples [0 ... N-1]^3
{ }% e# For each triple [a b c]:
_~ e# Make a copy, unwrap top one
{ }:F e# Define function F(x,y):
G@== e# x∗y (using table G)
~F e# Push a∗(b∗c)
\1m> e# Rotate triple right by 1
~ e# Unwrap rotated triple
F\F e# Push (a∗b)∗c
= e# Push 1 if a∗(b∗c) == (a∗b)∗c (associative), 0 otherwise
:* e# Multiply all the results together
e# 1 (true) only if F was associative for every [a b c]
ओह! काम के बहुत सारे, लेकिन अब हमने एन के सभी समूहों को एन (या बेहतर, इस पर संचालन - लेकिन सेट तय हो गया है, इसलिए यह एक ही बात है) की गणना की है। अगला चरण: आइसोमॉर्फिज्म का पता लगाएं। एक आइसोमोर्फिज्म उन दो समूहों के बीच एक जीव है जो x (x) y) = ∗ (x) φ ism (y) है । सीजेम में उन जीवों को उत्पन्न करना तुच्छ है: Ne!
यह करेंगे। हम उनकी जाँच कैसे कर सकते हैं? मेरा समाधान x । Y के लिए केली तालिका की दो प्रतियों से शुरू होता है । एक प्रति पर, φ सभी तत्वों के लिए लागू किया जाता है, पंक्तियों या स्तंभों के आदेश को बिना छुए। यह φ (x। Y) के लिए तालिका बनाता है । दूसरे पर तत्वों को वैसे ही छोड़ दिया जाता है जैसे वे हैं, लेकिन पंक्तियों और स्तंभों को φ के माध्यम से मैप किया जाता है । वह है, पंक्ति / स्तंभx पंक्ति / स्तंभ φ (x) बन जाता है । यह φ (x) φ y (y) के लिए तालिका बनाता है । अब जब हमारे पास दो टेबल हैं, तो हमें उनकी तुलना करना होगा: यदि वे समान हैं, तो हमने एक आइसोमोर्फिज्म पाया है।
बेशक, हम पर भी समरूपता का परीक्षण करने के लिए समूहों के जोड़े उत्पन्न करने की आवश्यकता है। हमें समूहों के सभी 2-संयोजनों की आवश्यकता है । ऐसा लगता है कि सीजेएम के पास संयोजन के लिए कोई ऑपरेटर नहीं है। हम उन्हें प्रत्येक समूह में ले जाकर और सूची में उसका अनुसरण करने वाले तत्वों के साथ जोड़कर उत्पन्न कर सकते हैं। मजेदार तथ्य: 2-संयोजनों की संख्या n × (n - 1) / 2 है , जो कि पहले n - प्राकृतिक संख्याओं का योग भी है । ऐसी संख्याओं को त्रिकोणीय संख्याएं कहा जाता है: पेपर पर एल्गोरिथ्म की कोशिश करें, प्रति पंक्ति एक निश्चित तत्व, और आप देखेंगे कि क्यों।
:L e# List of groups is on stack, store in L
,( e# Push len(L)-1
{ }fX e# For X in [0 ... len(L)-2]:
LX= e# Push the group L[X]
LX)> e# Push a slice of L excluding the first X+1 elements
1$ e# Push a copy of L[X]
f{...} e# Pass each [L[X] Y] combination to ... (see below)
e# The block will give back a list of Y for isomorphic groups
\a+ e# Append L[X] to the isomorphic groups
] e# Wrap everything in a list
ऊपर दिया गया कोड जोड़ी के पहले तत्व, L [X] को ठीक करता है , और इसे अन्य समूहों के साथ जोड़ता है (चलो उन Y में से प्रत्येक को कॉल करें )। यह जोड़ी को एक आइसोमोर्फिज्म टेस्ट ब्लॉक में पास करता है जिसे मैं एक पल में दिखाऊंगा। ब्लॉक Y के मूल्यों की एक सूची देता है जिसके लिए L [X] Y के लिए आइसोमोर्फिक है । तब L [X] को इस सूची में जोड़ा जाता है। यह समझने से पहले कि सूचियों को इस तरह से क्यों बनाया गया है, आइए आइज़ोमिफिज़्म टेस्ट देखें:
\_@ e# Push a copy of Y
a\a+ e# L[X] Y -> [L[X] Y]
Ne! e# Generate all bijective mappings
\f{ } e# For each bijection ([L[X] Y] extra parameter):
\:M; e# Store the mapping in M, pop it off the stack
~ e# [L[X] Y] -> L[X] Y
{ }2* e# Repeat two times (on Y):
M\f= e# Map rows (or transposed columns)
z e# Transpose rows and columns
e# This generates φ(x) ∗ φ(y)
\Mff= e# Map elements of L[X], generates φ(x ∗ y)
= e# Push 1 if the tables are equal, 0 otherwise
:| e# Push 1 if at least a mapping was isomorphic, 0 otherwise
{;}| e# If no mapping was isomorphic, pop the copy of Y off the stack
महान, अब हमारे पास सेट की एक सूची है जैसे [{L [0], Y1, Y2, ...}, {L [1], Y1, ...}, ...] । यहाँ विचार यह है कि, सकर्मक संपत्ति द्वारा, यदि किसी भी दो सेट में कम से कम एक तत्व है तो दो सेटों में सभी समूह आइसोमोर्फिक हैं। उन्हें एक सेट में एकत्र किया जा सकता है। जैसा कि L [X] L [X + ...] द्वारा बनाए गए संयोजनों में कभी नहीं दिखाई देगा , आइसोमॉर्फिज्म के प्रत्येक सेट को एकत्र करने के बाद एक अद्वितीय तत्व होगा। इसलिए, आइसोमोर्फिम्स की संख्या प्राप्त करने के लिए, यह गिनना पर्याप्त है कि आइसोमोर्फिम्स समूह के सभी सेटों में एक बार कितने समूह दिखाई देते हैं। ऐसा करने के लिए, मैं सेटों को खोल देता हूं ताकि वे दिखें [L [0], Y1, Y2, ..., L [1], Y1, ...] , उसी समूह के समूह बनाने के लिए सूची को क्रमबद्ध करें और अंत में। RLE- इसे एनकोड करें।
:~ e# Unwrap sets of isomorphic groups
$ e# Sort list
e` e# RLE-encode list
{ }, e# Filter RLE elements:
0= e# Get number of occurrences
1= e# Keep element if occurrences == 1
, e# Push length of filtered list
e# This is the number of groups up to isomorphism
बस आज के लिए इतना ही।