Liệu pháp nhóm: Xác định nhóm


17

Viết chương trình, xác định xem bảng nhân của magma hữu hạn đã cho có đại diện cho một nhóm hay không. Một magma là một tập hợp với một hoạt động nhị phân được đóng lại, có nghĩa là

  • với tất cả a, b trong G, a * b lại xuất hiện trong G (Độ kín)

Đặt (G, *) là một magma. (G, *) là một nhóm nếu

  • với mọi a, b, c trong G, (a * b) * c = a * (b * c) (Associativity)
  • tồn tại một phần tử e trong G sao cho e * a = a * e = a cho tất cả a trong G (Sự tồn tại của phần tử trung tính)
  • với tất cả a trong G có ab trong G sao cho a * b = b * a = e trong đó e là phần tử trung tính (Tồn tại nghịch đảo)

Thông số kỹ thuật

Đầu vào là một chuỗi gồm n ^ 2-1 ký tự (một ký tự cho mỗi phần tử của magma, được phép là 0-9, az) và chỉ đại diện cho bảng đọc từng hàng, bao gồm tên toán tử. Bạn có thể giả sử rằng đầu vào đại diện cho một magma hợp lệ (có nghĩa là mỗi phần tử xuất hiện chính xác một lần trong hàng tiêu đề / cột màu).

Ví dụ: Ở đây chúng tôi có bảng Z_4

+ | 0 1 2 3
-----------
0 | 0 1 2 3
1 | 1 2 3 0
2 | 2 3 0 1
3 | 3 0 1 2

Chuỗi đầu vào sẽ là 012300123112302230133012. (Hoặc nếu chúng ta sử dụng các ký hiệu thì nó cũng có thể nezdnnezdeezdnzzdneddnez). Xin lưu ý rằng chuỗi các phần tử trong hàng và trong cột không nhất thiết phải giống nhau, vì vậy bảng của Z_4 cũng có thể trông giống như vậy:

+ | 1 3 2 0
-----------
1 | 2 0 3 1
0 | 1 3 2 0
2 | 3 1 0 2
3 | 0 2 1 3

Điều này cũng có nghĩa là phần tử trung tính không nhất thiết phải ở cột đầu tiên hoặc hàng đầu tiên.

Nếu là một nhóm, chương trình phải trả về ký tự đại diện cho phần tử trung tính. Nếu không, nó phải trả về giá trị giả (khác với giá trị 0-9 az)

Các trường hợp thử nghiệm

Các nhóm không có thể dễ dàng được xây dựng chỉ bằng cách thay đổi một chữ số của chuỗi hoặc bằng cách thay đổi một cách giả tạo các bảng xác định một hoạt động mâu thuẫn với một trong các tiên đề của nhóm.

Các nhóm

Không đáng kể

* | x
-----
x | x

xxx

Neutral Element: x

H (nhóm bậc bốn)

* | p t d k g b n m 
-------------------
m | b d t g k p m n 
p | m k g d t n p b 
n | p t d k g b n m 
b | n g k t d m b p 
t | g m n p b k t d 
d | k n m b p g d t 
k | t b p m n d k g 
g | d p b n m t g k 

ptdkgbnmmbdtgkpmnpmkgdtnpbnptdkgbnmbngktdmbptgmnpbktddknmbpgdtktbpmndkggdpbnmtgk

Neutral Element: n

D_4

* | y r s t u v w x
-------------------
u | u x w v y t s r
v | v u x w r y t s
w | w v u x s r y t
x | x w v u t s r y
y | y r s t u v w x
r | r s t y v w x u
s | s t y r w x u v
t | t y r s x u v w


yrstuvwxuuxwvytsrvvuxwrytswwvuxsrytxxwvutsryyyrstuvwxrrstyvwxusstyrwxuvttyrsxuvw

Neutral Element: y

Z_6 x Z_2

x | 0 1 2 3 5 7 8 9 a b 4 6
---------------------------
0 | 0 1 2 3 5 7 8 9 a b 4 6 
1 | 1 2 3 4 0 8 9 a b 6 5 7 
2 | 2 3 4 5 1 9 a b 6 7 0 8 
7 | 7 8 9 a 6 2 3 4 5 0 b 1 
8 | 8 9 a b 7 3 4 5 0 1 6 2 
9 | 9 a b 6 8 4 5 0 1 2 7 3 
a | a b 6 7 9 5 0 1 2 3 8 4 
b | b 6 7 8 a 0 1 2 3 4 9 5 
3 | 3 4 5 0 2 a b 6 7 8 1 9 
4 | 4 5 0 1 3 b 6 7 8 9 2 a 
5 | 5 0 1 2 4 6 7 8 9 a 3 b 
6 | 6 7 8 9 b 1 2 3 4 5 a 0 

01235789ab46001235789ab4611234089ab6572234519ab67087789a623450b1889ab7345016299ab684501273aab6795012384bb678a0123495334502ab67819445013b67892a5501246789a3b66789b12345a0

Neutral Element: 0

A_4

* | i a b c d e f g h j k l
---------------------------
i | i a b c d e f g h j k l
a | a b i e c d g h f l j k
b | b i a d e c h f g k l j
c | c f j i g k a d l b e h
d | d h k b f l i e j a c g
e | e g l a h j b c k i d f
f | f j c k i g d l a h b e
g | g l e j a h c k b f i d
h | h k d l b f e j i g a c
j | j c f g k i l a d e h b
k | k d h f l b j i e c g a
l | l e g h j a k b c d f i

iabcdefghjkliiabcdefghjklaabiecdghfljkbbiadechfgkljccfjigkadlbehddhkbfliejacgeeglahjbckidfffjckigdlahbegglejahckbfidhhkdlbfejigacjjcfgkiladehbkkdhflbjiecgalleghjakbcdfi

Neutral Element: i

Không nhóm

Một vòng lặp (Nhóm thiếu tính kết hợp hoặc Nhóm Quasi với phần tử trung tính)

* | 1 2 3 4 5
-------------
1 | 1 2 3 4 5 
2 | 2 4 1 5 3 
3 | 3 5 4 2 1 
4 | 4 1 5 3 2 
5 | 5 3 2 1 4

12345112345224153335421441532553214

Neutral Element: 1
(2*2)*3 = 4*3 = 5 != 2 = 2*1 = 2*(2*3)

Vòng lặp IP (từ http://www.quasigroups.eu/contents/doad/2008/16_2.pdf )

* | 1 2 3 4 5 6 7
-----------------
1 | 1 2 3 4 5 6 7
2 | 2 3 1 6 7 5 4
3 | 3 1 2 7 6 4 5
4 | 4 7 6 5 1 2 3
5 | 5 6 7 1 4 3 2
6 | 6 4 5 3 2 7 1
7 | 7 5 4 2 3 1 6

123456711234567223167543312764544765123556714326645327177542316

Neutral Element: 1
2*(2*4) = 2*6 = 5 != 7 = 3*4 = (2*2)*4

Monoid (bởi Quincunx, cảm ơn!)

Đơn sắc là Magmas với tính kết hợp và một yếu tố trung tính.

* | 0 1 2 3
-----------
0 | 0 1 2 3
1 | 1 3 1 3
2 | 2 1 0 3
3 | 3 3 3 3

012300123113132210333333

Neutral Element: 0

Một Monoid khác

(Phép nhân mod 10, không có 5) Rõ ràng chúng ta không có nghịch đảo và tính kết hợp được đưa ra bởi phép nhân modulo 10.

* | 1 2 3 4 6 7 8 9
-------------------
1 | 1 2 3 4 6 7 8 9
2 | 2 4 6 8 2 4 6 8
3 | 3 6 9 2 8 1 4 7
4 | 4 8 2 6 4 8 2 6
6 | 6 2 8 4 6 2 8 4
7 | 7 4 1 8 2 9 6 3
8 | 8 6 4 2 8 6 4 2
9 | 9 8 7 6 4 3 2 1

Neutral Element: 1   12346789112346789224682468336928147448264826662846284774182963886428642998764321

Nghĩ rằng tôi sẽ thêm một bảng khác, lớn hơn nhiều, chỉ để cho vui: ideone.com/823aRG
Justin

Để cho vui, đây là một trò chơi thực sự lớn khác phá vỡ 0-9a-zquy tắc: ideone.com/vC0ewt
Justin

Đối với một người không biết gì về các nhóm, magma và như vậy, thông số kỹ thuật là mờ. Ví dụ, hoạt động giao hoán? (vì vậy bảng là dự phòng). Hơn thế nữa. vị trí của trung tính ở hàng đầu tiên không liên quan đến việc có cùng thứ tự trong hàng và cột: với 10101010thứ tự là như nhau và trung tính ở hàng và cột cuối cùng
edc65

Nhóm @edc không nhất thiết phải giao hoán (nhóm giao hoán được gọi là abelian). Định nghĩa của một nhóm là hoàn chỉnh (đó là định nghĩa thông thường), bất cứ điều gì bổ sung sẽ cung cấp thêm hạn chế. Trong các bảng đó, phép nhân với phần tử trung tính thường ở hàng / cột đầu tiên và chuỗi các phần tử của hàng / cột tiêu đề thường giống nhau, nhưng bạn vẫn có thể viết ra một bảng hợp lệ mà không tuân theo các quy ước đó. là những gì tôi muốn bao gồm ở đây.
flawr

1
Tôi đã xóa một số bình luận có vẻ là lỗi thời. Xin vui lòng thông báo cho tôi về bất kỳ ý kiến ​​nên được xóa.
Martin Ender

Câu trả lời:


4

Octave, 298 290 270 265 ký tự

function e=g(s)
c=@sortrows;d=a=c(c(reshape(a=[0 s],b=numel(a)^.5,b)')');
for i=2:b a(a==a(i))=i-1;end;
a=a(2:b,2:b--);u=1:b;
e=(isscalar(e=find(all(a==u')))&&a(e,:)==u&&sum(t=a==e)==1&&t==t')*e;
for x=u for y=u for z=u e*=a(a(x,y),z)==a(x,a(y,z));end;end;end;e=d(e+1);

265: Loại bỏ chức năng xử lý không cần thiết.

270: Xét cho cùng, việc kiểm tra đó e==hcho e luôn làm hài lòng e · một = ah luôn đáp ứng một · h = a là không cần thiết. Điều này là không thể đối với họ khác nhau ( e · h =? ).

Các chi tiết từ lời giải thích cho giải pháp dưới đây vẫn có liên quan.


290:

function e=g(s)
c=@sortrows;d=a=c(c(reshape(a=[0 s],b=numel(a)^.5,b)')');
for i=2:b a(a==a(i))=i-1;end;
a=a(2:b,2:b--);u=1:b;
s=@isscalar;e=(s(e=find(all(a==u')))&&s(h=find(all(a'==u')'))&&sum(t=a==e)==1&&t==t')*e;
for x=u for y=u for z=u e*=a(a(x,y),z)==a(x,a(y,z));end;end;end;e=d(e+1);

Dòng đầu tiên

c=@sortrows;d=a=c(c(reshape(a=[0 s],b=numel(a)^.5,b)')'); chỉ lưu trữ đầu vào vào bảng nxn (không có ký tự ở vị trí dấu hoạt động), sau đó sắp xếp các cột và hàng theo từ vựng để các hàng và cột nhận được cùng một thứ tự:

+ | z a t b                        + | a b t z
-----------                        -----------
z | t b a z         becomes        a | t a z b
b | z a t b      ============>     b | a b t z
t | a z b t                        t | z t b a
a | b t z a                        z | b z a t

Bây giờ, tôi sắp xếp lại "a","b","t","z"theo tiêu chuẩn 1, 2, 3, 4, để tôi có thể lập chỉ mục bảng một cách hiệu quả. Điều này được thực hiện bởi các dòng for i=2:b a(a==a(i))=i-1;end;. Nó mang lại bảng như

0   1   2   3   4
1   3   1   4   2
2   1   2   3   4
3   4   3   2   1
4   2   4   1   3

, nơi chúng ta có thể thoát khỏi hàng và cột đầu tiên với a=a(2:b,2:b--);u=1:b;:

3  1  4  2
1  2  3  4
4  3  2  1
2  4  1  3

Bảng này có các thuộc tính đã cho:

  • nếu phần tử trung tính e tồn tại, chính xác một hàng ( isscalar) và một cột có giá trị của vectơ hàng u=[1 2 3 ... number-of-elements]:

s=@isscalar;e=(s(e=find(all(a==u')))&&s(h=find(all(a'==u')'))&&...

  • nếu mỗi phần tử a có phần tử ngược a ' , hai điều giữ: phần tử trung tính e chỉ xảy ra một lần mỗi cột và chỉ một lần mỗi hàng ( sum(t=a==e)==1) và, để thỏa mãn a' · a = a · a ' , các lần xuất hiện của e là đối xứng về dịch thuậtt==t'

  • a · b có thể được lấy bằng cách t(a,b)lập chỉ mục đơn giản . Sau đó, chúng tôi kiểm tra tính kết hợp trong vòng lặp nhàm chán:

for x=u for y=u for z=u e*=a(a(x,y),z)==a(x,a(y,z));end;end;end;

Hàm trả về phần tử trung tính theo cách nó xuất hiện trong bảng gốc ( e=d(e+1)) hoặc ký tự nil nếu bảng không mô tả một nhóm.


2
Làm tốt và giải thích tốt. Nên trả lại phần tử trung tính thay vì 1.
edc65

Đã sửa, bây giờ trả về giá trị thích hợp.
pawel.boczarski

1
OCTAVE FTW =) Tôi không chắc chắn về hai điều (đến từ matlab), nhưng có lẽ bạn có thể sử dụng nó để cải thiện câu trả lời của mình: Có thể giảm `a (f (a == a (i))) = i-1` để a(a==a(i))=i-1? Khác hơn là bạn có thể sử dụng (...)^.5thay vì sqrt(...).
flawr

@flawr Cảm ơn, cả hai đều hoạt động trong quãng tám (phiên bản 3.8.1).
pawel.boczarski

6

Ruby, 401 ... 272

f=->s{n=(s.size+1)**0.5
w=n.to_i-1
e=s[0,w].split''
s=s[w,n*n]
m={}
w.times{(1..w).each{|i|m[s[0]+e[i-1]]=s[i]}
s=s[n,n*n]}
s=e.find{|a|e.all?{|b|x=m[a+b]
x==m[b+a]&&x==b}}
e.all?{|a|t=!0
e.all?{|b|x=m[a+b]
t||=x==m[b+a]&&x==s
e.all?{|c|m[m[a+b]+c]==m[a+m[b+c]]}}&&t}&&s}

Đây là chương trình ruby ​​đầu tiên của tôi! Điều này xác định một hàm lambda mà chúng ta có thể kiểm tra bằng cách thực hiện puts f[gets.chomp]. Tôi trả lại falsecho giá trị sai của tôi. Nửa đầu của hàm chỉ đơn giản là phân tích cú pháp đầu vào thành bản đồ, sau đó nửa thứ hai kiểm tra các khả năng.

f=->s{
    n=((s.size+1)**0.5).to_i
    w=n-1
    e=s[0,w].split'' # create an array of elements of the potential group
    s=s[w,n*n]
    m={} # this map is what defines our operation
    w.times{
        (1..w).each{               # for each element in the row of the table
            |i|m[s[0]+e[i-1]]=s[i] # put the value into the map
        }
        s=s[n,n*n]
    }
    s=e.find{|a| # s is the identity
        e.all?{|b|
            x=m[a+b]
            x==m[b+a]&&x==b # is a the identity?
        }
    }
    e.all?{|a| # implicit return statement
        t = !0 # t = false
        e.all?{|b| # check for inverses
            x=m[a+b]
            t ||= x==m[b+a]&&x==s # t is now true if b was a's inverse
            e.all?{|c|
                m[m[a+b]+c]==m[a+m[b+c]] # check associativity
            }
        } && t
    }&&s
}

5
Chào mừng bạn đến với những điều kỳ diệu của việc chơi golf trong Ruby! ;) nillà một giá trị giả ngắn hơn false. Các hàm có thể được định nghĩa là lambdas như thế q=->{abort'false'}(nếu chúng lấy tham số, sau đó sử dụng []để gọi chúng thay vì ()). Tôi tin rằng .charsđã cung cấp cho bạn một mảng, vì vậy không cần .to_a. Nếu bạn không cần một dòng mới kéo dài $><<hơn một byte so putsvới không gian cộng. Hash.newkhông cần dấu ngoặc đơn. Đó là tất cả những gì tôi có thể thấy bây giờ. Giữ nó lên! ;)
Martin Ender

Các charsđiều là số lẻ. Bạn đang sử dụng phiên bản nào của Ruby?
Martin Ender

@ MartinBüttner 1.9.3
Justin

À, đúng rồi, tôi đã xem tài liệu của 2.1.5.
Martin Ender

1
Bạn có thể thay thế Math.sqrt(...)bằng ...**0.5. Ngoài ra, a if bcó thể được viết lại: b&&ađể tránh hai khoảng trống
Cristian Lupascu

4

JavaScript (ES6) 285 243 278

Chạy đoạn mã để kiểm tra (là ES6, nó chỉ hoạt động trên Firefox)

Chỉnh sửa 2 sửa lỗi. Tôi đã sai trong việc tìm ra yếu tố trung tính, chỉ kiểm tra một cách. (Cần trường hợp kiểm tra tốt hơn !!!)

Chỉnh sửa Sử dụng nối chuỗi đơn giản hơn thay vì chỉ mục kép (như @Quincunx), tôi không biết mình đang nghĩ gì. Ngoài ra, kiểm tra nghịch đảo đơn giản, nó vẫn hoạt động.

F=t=>(
  e=t.slice(0,d=Math.sqrt(t.length)|0),
  t=t.slice(d).match('.'.repeat(d+1),'g'),
  t.map(r=>{
    for(v=r[i=0],
        j=e.search(v)+1, // column for current row  element
        r!=v+e|t.some(r=>r[j]!=r[0])?0:n=v; // find neutral
        c=r[++i];
       )h[v+e[i-1]]=c
  },h={},n=''),
  e=[...e],!e.some(a=>e.some(b=>(
    h[a+b]==n&&--d, // inverse
    e.some(c=>h[h[a+b]+c]!=h[a+h[b+c]]) // associativity
  )
  ))&&!d&&n
)
input { width: 400px; font-size:10px }
Click on textbox to test - Result : <span id=O></span><br>
<input value='...' onclick='O.innerHTML=F(this.value)'> (?)
<br>Groups<br>
<input value='nezdnnezdeezdnzzdneddnez' onclick='O.innerHTML=F(this.value)'> (n)<br>
<input value='ptdkgbnmmbdtgkpmnpmkgdtnpbnptdkgbnmbngktdmbptgmnpbktddknmbpgdtktbpmndkggdpbnmtgk' onclick='O.innerHTML=F(this.value)'> (n)<br>
<input value='yrstuvwxuuxwvytsrvvuxwrytswwvuxsrytxxwvutsryyyrstuvwxrrstyvwxusstyrwxuvttyrsxuvw' onclick='O.innerHTML=F(this.value)'> (y)<br>
<input value='01235789ab46001235789ab4611234089ab6572234519ab67087789a623450b1889ab7345016299ab684501273aab6795012384bb678a0123495334502ab67819445013b67892a5501246789a3b66789b12345a0'onclick='O.innerHTML=F(this.value)'> (0)<br>
Non groups <br>
<input value='12345112345224153335421441532553214' onclick='O.innerHTML=F(this.value)'> (FAIL)<br>
<input value='123456711234567223167543312764544765123556714326645327177542316' onclick='O.innerHTML=F(this.value)'> (FAIL)<br>
<input value='012300123113132210333333' onclick='O.innerHTML=F(this.value)'> (FAIL)<br>


2

Haskell 391B

import Data.Maybe
import Data.List
o a b=elemIndex b a
l£a=fromJust.o a$l
a§b=[a!!i|i<-b]
f s|isJust j&&and(map(isJust.o h)s)&&and[or[p%q==e|q<-h]&&and[p%(q%r)==(p%q)%r|q<-h,r<-h]|p<-h]=[e]|True="!"where n=floor$(sqrt(fromIntegral$length s+1))-1;h=take n s;g=[s§[a..b]|(a,b)<-zip[1+n,2+n+n..][n+n,3*n+1..(n+1)^2]];v=s§[n,1+2*n..n+n*n];a%b=g!!(b£v)!!(a£h);j=o g h;e=v!!fromJust j

Nguyền rủa những kẻ đó import!

import Data.Maybe
import Data.List

{- rename elemIndex to save characters -}
o a b=elemIndex b a

{- get the index of l in a -}
l£a=fromJust.o a$l

{- extract a sublist of a with indices b -}
a§b=[a!!i|i<-b]

f s |isJust j {-Identity-}
     &&and (map (isJust.o h) s) {-Closure-}
     &&and[
        or [p%q==e|q<-h] {-Inverse-}
        && and [ p%(q%r)==(p%q)%r | q<-h,r<-h ] {-Associativity-}
     |
        p<-h
     ]=[e]
    |True="!"
    where
    {-size-}    n=floor$(sqrt(fromIntegral$length s+1))-1
    {-horiz-}   h=take n s
    {-table-}   g=[s§[a..b]|(a,b)<-zip[1+n,2+n+n..][n+n,3*n+1..(n+1)^2]]
    {-vert-}    v=s§[n,1+2*n..n+n*n]
    {-operate-} a%b=g!!(b£v)!!(a£h)
                j=o g h {-index of the first row identical to the top-}
    {-ident-}   e=v!!fromJust j

Giải trình

f::String->Stringánh xạ chuỗi tới một trong hai e::Charphần tử nhận dạng hoặc !.

Các wherekhoản tạo ra một loạt các biến và chức năng, mà tôi đã nhận xét; v::[Int]là danh sách dọc của các phần tử, một phần tử h::[Int]ngang.

%::Char->Char->Char áp dụng hoạt động nhóm cho các đối số của nó.

g::[[Int]]là bảng nhóm (dành cho hội nghị sử dụng %)

j::Maybe Intchứa chỉ mục của danh tính vnếu nó tồn tại, nếu không Nothing, đó là lý do tại sao isJust jđiều kiện trong fdanh tính.


Bạn có thể giải thích một chút những gì đang xảy ra ở đây?
xebtl

Tôi đã thêm một vài nhận xét, nhưng ý chính cơ bản là 'áp dụng các bài kiểm tra cho bảng nhóm'. Lưu ý đó {- -}là một nhận xét. Bạn có bất kỳ câu hỏi cụ thể hơn, hoặc làm rõ nó?
alexander-brett

Cảm ơn. Tôi đoán để thực sự hiểu nó, tôi sẽ cần học một số Haskell trước :-)
xebtl
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.