ทับทิม
พื้นหลัง
polytope ปกติมีสามตระกูลขยายเป็นมิติที่ไม่มีที่สิ้นสุด:
simplexes ซึ่งจัตุรมุขเป็นสมาชิก (ฉันมักจะอ้างถึงพวกเขาที่นี่เป็นไฮเพทราเฮดราแม้ว่าคำว่าเริมจะถูกต้องมากขึ้น) สัญลักษณ์ schlafi ของพวกเขาอยู่ในรูปแบบ {3,3,...,3,3}
n-cubes ซึ่ง cube เป็นสมาชิก สัญลักษณ์ schlafi เป็นแบบฟอร์ม{4,3,...,3,3}
orthoplexes ซึ่งแปดด้านเป็นสมาชิก (ฉันมักจะอ้างถึงพวกเขาที่นี่เป็น hyperoctahedra) สัญลักษณ์ schlafi ของพวกเขาอยู่ในรูปแบบ {3,3,...,3,4}
มีครอบครัวอนันต์เพิ่มเติมอีกหนึ่งแห่งของ polytopes ปกติสัญลักษณ์{m}
ของรูปหลายเหลี่ยม 2 มิติซึ่งอาจมีขอบจำนวน m ใด ๆ
นอกจากนี้ยังมีอีกห้ากรณีพิเศษอื่น ๆ ของ polytope ปกติคือ icosahedron 3 มิติ{3,5}
และ dodecahedron {5,3}
; analogues 4 มิติของพวกเขา 600 เซลล์{3,3,5}
และ 120 เซลล์{5,3,3}
; และอีกหนึ่งมิติ polytope 4 มิติ 24 เซลล์{3,4,3}
(ซึ่งมี analogues ที่ใกล้ที่สุดใน 3 มิติคือ cuboctahedron และคู่ dombecahedron ขนมเปียกปูนของมัน)
ฟังก์ชั่นหลัก
ด้านล่างเป็นpolytope
ฟังก์ชั่นหลักที่ตีความสัญลักษณ์ schlafi คาดว่าจะมีอาร์เรย์ของตัวเลขและส่งกลับอาร์เรย์ที่มีกลุ่มของอาร์เรย์ดังนี้
อาเรย์ของจุดยอดทั้งหมดแต่ละอันแสดงเป็นอาเรย์ n-element ของพิกัด (โดยที่ n คือจำนวนมิติ)
อาเรย์ของขอบทั้งหมดแต่ละอันแสดงเป็น 2 องค์ประกอบของดัชนีจุดสุดยอด
อาร์เรย์ของใบหน้าทั้งหมดแต่ละหน้าแสดงเป็นองค์ประกอบ m ของดัชนีจุดยอด (โดยที่ m คือจำนวนจุดยอดต่อหน้า)
และอื่น ๆ ตามความเหมาะสมกับจำนวนมิติ
มันคำนวณ 2d polytopes ของตัวเองเรียกใช้ฟังก์ชันสำหรับตระกูล infinite 3 มิติและใช้ตารางการค้นหาสำหรับกรณีพิเศษห้ากรณี มันคาดว่าจะพบฟังก์ชั่นและตารางที่ประกาศไว้ข้างต้น
include Math
#code in subsequent sections of this answer should be inserted here
polytope=->schl{
if schl.size==1 #if a single digit calculate and return a polygon
return [(1..schl[0]).map{|i|[sin(PI*2*i/schl[0]),cos(PI*2*i/schl[0])]},(1..schl[0]).map{|i|[i%schl[0],(i+1)%schl[0]]}]
elsif i=[[3,5],[5,3]].index(schl) #if a 3d special, lookup from tables
return [[vv,ee,ff],[uu,aa,bb]][i]
elsif i=[[3,3,5],[5,3,3],[3,4,3]].index(schl) #if a 4d special. lookup fromm tables
return [[v,e,f,g],[u,x,y,z],[o,p,q,r]][i]
elsif schl.size==schl.count(3) #if all threes, call tetr for a hypertetrahedron
return tetr[schl.size+1]
elsif schl.size-1==schl.count(3) #if all except one number 3
return cube[schl.size+1] if schl[0]==4 #and the 1st digit is 4, call cube for a hypercube
return octa[schl.size+1] if schl[-1]==4 #and the last digit is 4, call octa for a hyperoctahedron
end
return "error" #in any other case return an error
}
ฟังก์ชั่นสำหรับจัตุรมุขลูกบาศก์และแปดตระกูล
https://en.wikipedia.org/wiki/Simplex
https://en.wikipedia.org/wiki/5-cell (4d simplex)
http://mathworld.wolfram.com/Simplex.html
คำอธิบายตระกูล Tetrahedron - พิกัด
Simplex / Hyperetrahedron แบบ n-dimensional มี n + 1 คะแนน มันง่ายมากที่จะให้จุดยอดของ n-dimension simplex ใน n + 1 มิติ
ดังนั้น(1,0,0),(0,1,0),(0,0,1)
อธิบายสามเหลี่ยม 2d ที่ฝังใน 3 มิติและ(1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)
อธิบายจัตุรมุข 3 มิติที่ฝังใน 4 มิติ สิ่งนี้สามารถตรวจสอบได้อย่างง่ายดายโดยการยืนยันว่าระยะทางทั้งหมดระหว่างจุดยอดคือ sqrt (2)
อัลกอริทึมที่ซับซ้อนต่าง ๆ จะได้รับบนอินเทอร์เน็ตสำหรับการค้นหาจุดยอดสำหรับซิมเพล็กซ์ในพื้นที่มิติ ผมพบว่าหนึ่งง่ายอย่างน่าทึ่งในความคิดเห็นจะ Jagy ในคำตอบนี้/mathpro//a/38725 จุดสุดท้ายอยู่บนเส้นp=q=...=x=y=z
ที่ระยะของ sqrt (2) จากคนอื่น ๆ ดังนั้นสามเหลี่ยมดังกล่าวข้างต้นสามารถแปลงเป็นจัตุรมุขโดยนอกเหนือจากจุดที่ทั้งหรือ(-1/3,-1/3,-1/3)
(1,1,1)
2 ค่าที่เป็นไปได้เหล่านี้ของพิกัดสำหรับจุดสุดท้ายจะถูกกำหนดโดย(1-(1+n)**0.5)/n
และ(1+(1+n)**0.5)/n
ตามที่คำถามบอกว่าขนาดของ n-tope ไม่สำคัญฉันต้องการคูณด้วย n และใช้พิกัด(n,0,0..0)
จนถึง(0..0,0,n)
จุดสุดท้าย(t,t,..,t,t)
ที่ t = 1-(1+n)**0.5
เพื่อความเรียบง่าย
เนื่องจากศูนย์กลางของจัตุรมุขนี้ไม่ได้อยู่ที่จุดกำเนิดการแก้ไขพิกัดทั้งหมดจะต้องทำโดยเส้นs.map!{|j|j-((1-(1+n)**0.5)+n)/(1+n)}
ที่ค้นหาว่าศูนย์กลางอยู่ไกลจากจุดกำเนิดและลบออก ฉันเก็บสิ่งนี้ไว้เป็นการดำเนินการแยกต่างหาก อย่างไรก็ตามฉันได้ใช้s[i]+=n
ตำแหน่งที่s[i]=n
จะทำเพื่ออ้างอิงถึงความจริงที่ว่าเมื่ออาเรย์เริ่มต้นโดยs=[0]*n
เราสามารถใส่ออฟเซ็ตที่ถูกต้องที่นี่แทนและทำการแก้ไขที่กึ่งกลางที่จุดเริ่มต้นแทนที่จะจบ
คำอธิบายตระกูล Tetrahedron - ทอพอโลยีกราฟ
กราฟของ simplex เป็นกราฟที่สมบูรณ์: ทุกจุดยอดจะเชื่อมต่อกันทุกครั้งที่จุดยอดอื่น ๆ หากเรามี n simplex เราสามารถลบจุดสุดยอดใด ๆ เพื่อให้ n-1 simplex ลงไปจนถึงจุดที่เรามีรูปสามเหลี่ยมหรือแม้แต่ขอบ
ดังนั้นเราจึงมีทั้งหมด 2 รายการ ** (n + 1) ไปยังแคตตาล็อกซึ่งแต่ละรายการจะแสดงด้วยเลขฐานสอง ช่วงนี้จากทั้งหมด0
เพื่อความว่างเปล่าผ่านหนึ่ง1
สำหรับจุดสุดยอดและสอง1
s สำหรับขอบถึงถึงทั้งหมด1
สำหรับ polytope ที่สมบูรณ์
เราตั้งค่าอาร์เรย์ของอาร์เรย์ที่ว่างเปล่าเพื่อจัดเก็บองค์ประกอบของแต่ละขนาด จากนั้นเราวนรอบจากศูนย์ถึง (2 ** n + 1) เพื่อสร้างเซตย่อยที่เป็นไปได้ของแต่ละจุดและเก็บไว้ในอาร์เรย์ตามขนาดของแต่ละชุดย่อย
เราไม่สนใจในสิ่งที่เล็กกว่าขอบ (จุดยอดหรือศูนย์) หรือในโพลีท็อปที่สมบูรณ์ (เนื่องจากลูกบาศก์ที่สมบูรณ์ไม่ได้ให้ไว้ในตัวอย่างในคำถาม) ดังนั้นเราจึงกลับtg[2..n]
ไปลบองค์ประกอบที่ไม่ต้องการเหล่านี้ ก่อนจะกลับมาเราจะทำการ [ทีวี] ที่มีพิกัดจุดยอดเข้าสู่จุดเริ่มต้น
รหัส
tetr=->n{
#Tetrahedron Family Vertices
tv=(0..n).map{|i|
s=[0]*n
if i==n
s.map!{(1-(1+n)**0.5)}
else
s[i]+=n
end
s.map!{|j|j-((1-(1+n)**0.5)+n)/(1+n)}
s}
#Tetrahedron Family Graph
tg=(0..n+1).map{[]}
(2**(n+1)).times{|i|
s=[]
(n+1).times{|j|s<<j if i>>j&1==1}
tg[s.size]<<s
}
return [tv]+tg[2..n]}
cube=->n{
#Cube Family Vertices
cv=(0..2**n-1).map{|i|s=[];n.times{|j|s<<(i>>j&1)*2-1};s}
#Cube Family Graph
cg=(0..n+1).map{[]}
(3**n).times{|i| #for each point
s=[]
cv.size.times{|j| #and each vertex
t=true #assume vertex goes with point
n.times{|k| #and each pair of opposite sides
t&&= (i/(3**k)%3-1)*cv[j][k]!=-1 #if the vertex has kingsmove distance >1 from point it does not belong
}
s<<j if t #add the vertex if it belongs
}
cg[log2(s.size)+1]<<s if s.size > 0
}
return [cv]+cg[2..n]}
octa=->n{
#Octahedron Family Vertices
ov=(0..n*2-1).map{|i|s=[0]*n;s[i/2]=(-1)**i;s}
#Octahedron Family Graph
og=(0..n).map{[]}
(3**n).times{|i| #for each point
s=[]
ov.size.times{|j| #and each vertex
n.times{|k| #and each pair of opposite sides
s<<j if (i/(3**k)%3-1)*ov[j][k]==1 #if the vertex is located in the side corresponding to the point, add the vertex to the list
}
}
og[s.size]<<s
}
return [ov]+og[2..n]}
คำอธิบายตระกูล cube และ octahedron - พิกัด
n-cube มี2**n
จุดยอดแต่ละอันแสดงโดยอาร์เรย์ของ n 1
s และ-1
s (เป็นไปได้ทั้งหมดที่ได้รับอนุญาต) เราวนซ้ำดัชนี0
ไป2**n-1
ยังรายการของจุดยอดทั้งหมดและสร้างอาร์เรย์สำหรับจุดยอดแต่ละจุดด้วยการวนซ้ำผ่านบิตของ ดัชนีและการเพิ่ม-1
หรือ1
อาร์เรย์ (น้อยนิดที่สำคัญในการบิตที่สำคัญที่สุด.) ดังนั้นไบนารีจะกลายเป็นจุด1101
4d[1,-1,1,1]
n-แปดหรือ n-orthoplex มี2n
จุดพิกัดศูนย์ทั้งหมดยกเว้นหนึ่งซึ่งจะเป็นหรือ1
ลำดับของจุดในอาร์เรย์ที่สร้างขึ้นมี-1
[[1,0,0..],[-1,0,0..],[0,1,0..],[0,-1,0..],[0,0,1..],[0,0,-1..]...]
โปรดทราบว่าในขณะที่รูปแปดด้านนั้นเป็นคู่ของลูกบาศก์จุดยอดของรูปแปดด้านจะถูกกำหนดโดยศูนย์กลางของใบหน้าของก้อนที่ล้อมรอบ
คำอธิบายตระกูล cube และ octahedron - ทอพอโลยีกราฟ
แรงบันดาลใจบางอย่างมาจากด้าน Hypercubeและความจริงที่ว่า hyperoctahedron เป็นสองเท่าของ hypercube
สำหรับ n-cube มี3**n
รายการที่จะแคตตาล็อก ตัวอย่างเช่น 3 cube มี3**3
= 27 องค์ประกอบ สิ่งนี้สามารถเห็นได้จากการศึกษาลูกบาศก์ของรูบิคซึ่งมีศูนย์ 1, 6 ใบหน้า, 12 ขอบและ 8 จุดยอดรวม 27 เราวนซ้ำไปจนถึง -1,0 และ -1 ในทุกมิติที่กำหนด n-cube ของความยาว 2x2x2 .. และกลับจุดยอดทั้งหมดที่ไม่ได้อยู่ฝั่งตรงข้ามของลูกบาศก์ ดังนั้นศูนย์กลางของคิวบ์จะส่งคืนจุดยอดทั้ง 2 ** n และการย้ายหนึ่งหน่วยออกจากศูนย์กลางตามแนวแกนใด ๆ จะลดจำนวนจุดยอดลงครึ่งหนึ่ง
เช่นเดียวกับตระกูลจัตุรมุขเราเริ่มต้นด้วยการสร้างอาร์เรย์ที่ว่างและเติมตามจำนวนจุดยอดต่อองค์ประกอบ โปรดทราบว่าเนื่องจากจำนวนของจุดแตกต่างกันเป็น 2 ** n ในขณะที่เราขึ้นไปถึงขอบใบหน้า, ก้อน ฯลฯ เราใช้แทนที่จะlog2(s.size)+1
s.size
อีกครั้งเราต้องลบไฮเปอร์คิวบ์ออกและองค์ประกอบทั้งหมดที่มีจุดยอดน้อยกว่า 2 อันก่อนกลับจากฟังก์ชัน
Octahedron / orthoplex เป็นสองเท่าของตระกูล cube ดังนั้นจึงมี3**n
ไอเท็มแค็ตตาล็อก ที่นี่เราวนซ้ำ-1,0,1
สำหรับมิติทั้งหมดและหากพิกัดที่ไม่ใช่ศูนย์ของจุดยอดเท่ากับพิกัดที่สอดคล้องกันของจุดจุดยอดจะถูกเพิ่มเข้าไปในรายการที่สอดคล้องกับจุดนั้น ดังนั้นขอบจึงตรงกับจุดที่มีสองค่าที่ไม่ใช่ศูนย์, สามเหลี่ยมไปยังจุดที่มี 3 ค่าที่ไม่ใช่ศูนย์และ tetrahedron ไปยังจุดที่มี 4 หน้าสัมผัสที่ไม่ใช่ศูนย์ (ในพื้นที่ 4d)
อาร์เรย์ผลลัพธ์ของจุดสุดยอดสำหรับแต่ละจุดจะถูกเก็บไว้ในอาร์เรย์ขนาดใหญ่เช่นเดียวกับกรณีอื่นและเราต้องลบองค์ประกอบใด ๆ ที่มีจุดยอดน้อยกว่า 2 จุดก่อนที่จะกลับมา แต่ในกรณีนี้เราไม่จำเป็นต้องลบพาเรนต์ n-tope ทั้งหมดเนื่องจากอัลกอริทึมไม่ได้บันทึกไว้
การใช้งานของรหัสสำหรับคิวบ์ได้รับการออกแบบให้มีความคล้ายคลึงกันมากที่สุด ขณะนี้มีความสง่างามบางอย่างเป็นไปได้ว่าอัลกอริทึมที่มีประสิทธิภาพมากขึ้นตามหลักการเดียวกันนี้สามารถสร้างขึ้นมาได้
https://en.wikipedia.org/wiki/Hypercube
http://mathworld.wolfram.com/Hypercube.html
https://en.wikipedia.org/wiki/Cross-polytope
http://mathworld.wolfram.com/CrossPolytope.html
รหัสสำหรับการสร้างตารางสำหรับกรณีพิเศษ 3 มิติ
มีการใช้การวางแนวของ icosahedron / dodecahedron โดยใช้แกนสมมาตรห้าเท่าที่ขนานกับมิติสุดท้ายซึ่งใช้สำหรับการติดฉลากที่สอดคล้องกันของชิ้นส่วน การนับจำนวนจุดยอดและใบหน้าสำหรับ icosahedron นั้นเป็นไปตามแผนภาพในการแสดงความคิดเห็นเกี่ยวกับโค้ดและกลับไปหา dodecahedron
ตามhttps://en.wikipedia.org/wiki/Regular_icosahedronละติจูดของจุดยอดที่ไม่มีขั้ว 10 ขั้วของ icosahedron คือ +/- arctan (1/2) พิกัดของ 10 จุดยอดแรกของ icosahedron นั้นคำนวณจาก นี่บนรัศมีสองวง 2 ที่ระยะทาง +/- 2 จากระนาบ xy สิ่งนี้ทำให้รัศมีโดยรวมของ circumsphere sqrt (5) ดังนั้นจุดยอด 2 อันสุดท้ายอยู่ที่ (0,0, + / - - sqrt (2))
พิกัดของจุดยอดของทรงสิบสองเหลี่ยมคำนวณโดยการหาพิกัดของจุดยอดสามอันที่ล้อมรอบพวกมัน
=begin
TABLE NAMES vertices edges faces
icosahedron vv ee ff
dodecahedron uu aa bb
10
/ \ / \ / \ / \ / \
/10 \ /12 \ /14 \ /16 \ /18 \
-----1-----3-----5-----7-----9
\ 0 / \ 2 / \ 4 / \ 6 / \ 8 / \
\ / 1 \ / 3 \ / 5 \ / 7 \ / 9 \
0-----2-----4-----6-----8-----
\11 / \13 / \15 / \17 / \19 /
\ / \ / \ / \ / \ /
11
=end
vv=[];ee=[];ff=[]
10.times{|i|
vv[i]=[2*sin(PI/5*i),2*cos(PI/5*i),(-1)**i]
ee[i]=[i,(i+1)%10];ee[i+10]=[i,(i+2)%10];ee[i+20]=[i,11-i%2]
ff[i]=[(i-1)%10,i,(i+1)%10];ff[i+10]=[(i-1)%10,10+i%2,(i+1)%10]
}
vv+=[[0,0,-5**0.5],[0,0,5**0.5]]
uu=[];aa=[];bb=[]
10.times{|i|
uu[i]=(0..2).map{|j|vv[ff[i][0]][j]+vv[ff[i][1]][j]+vv[ff[i][2]][j]}
uu[i+10]=(0..2).map{|j|vv[ff[i+10][0]][j]+vv[ff[i+10][1]][j]+vv[ff[i+10][2]][j]}
aa[i]=[i,(i+1)%10];aa[i+10]=[i,(i+10)%10];aa[i+20]=[(i-1)%10+10,(i+1)%10+10]
bb[i]=[(i-1)%10+10,(i-1)%10,i,(i+1)%10,(i+1)%10+10]
}
bb+=[[10,12,14,16,18],[11,13,15,17,19]]
รหัสสำหรับการสร้างตารางสำหรับกรณีพิเศษ 4d
นี่เป็นบิตของการแฮ็ก รหัสนี้ใช้เวลาสองสามวินาทีในการเรียกใช้ มันจะดีกว่าที่จะเก็บผลลัพธ์ในไฟล์และโหลดตามที่ต้องการ
รายการ 120 พิกัดจุดสุดยอดสำหรับ 600cell คือจากhttp://mathworld.wolfram.com/600-Cell.html พิกัด 24 จุดยอดที่ไม่มีอัตราส่วนทองคำในรูปจุดยอดของเซลล์ 24 เซลล์ Wikipedia มีรูปแบบเหมือนกัน แต่มีข้อผิดพลาดในระดับสัมพัทธ์ของ 24 พิกัดเหล่านี้และอีก 96
#TABLE NAMES vertices edges faces cells
#600 cell (analogue of icosahedron) v e f g
#120 cell (analogue of dodecahedron) u x y z
#24 cell o p q r
#600-CELL
# 120 vertices of 600cell. First 24 are also vertices of 24-cell
v=[[2,0,0,0],[0,2,0,0],[0,0,2,0],[0,0,0,2],[-2,0,0,0],[0,-2,0,0],[0,0,-2,0],[0,0,0,-2]]+
(0..15).map{|j|[(-1)**(j/8),(-1)**(j/4),(-1)**(j/2),(-1)**j]}+
(0..95).map{|i|j=i/12
a,b,c,d=1.618*(-1)**(j/4),(-1)**(j/2),0.618*(-1)**j,0
h=[[a,b,c,d],[b,a,d,c],[c,d,a,b],[d,c,b,a]][i%12/3]
(i%3).times{h[0],h[1],h[2]=h[1],h[2],h[0]}
h}
#720 edges of 600cell. Identified by minimum distance of 2/phi between them
e=[]
120.times{|i|120.times{|j|
e<<[i,j] if i<j && ((v[i][0]-v[j][0])**2+(v[i][1]-v[j][1])**2+(v[i][2]-v[j][2])**2+(v[i][3]-v[j][3])**2)**0.5<1.3
}}
#1200 faces of 600cell.
#If 2 edges share a common vertex and the other 2 vertices form an edge in the list, it is a valid triangle.
f=[]
720.times{|i|720.times{|j|
f<< [e[i][0],e[i][1],e[j][1]] if i<j && e[i][0]==e[j][0] && e.index([e[i][1],e[j][1]])
}}
#600 cells of 600cell.
#If 2 triangles share a common edge and the other 2 vertices form an edge in the list, it is a valid tetrahedron.
g=[]
1200.times{|i|1200.times{|j|
g<< [f[i][0],f[i][1],f[i][2],f[j][2]] if i<j && f[i][0]==f[j][0] && f[i][1]==f[j][1] && e.index([f[i][2],f[j][2]])
}}
#120 CELL (dual of 600 cell)
#600 vertices of 120cell, correspond to the centres of the cells of the 600cell
u=g.map{|i|s=[0,0,0,0];i.each{|j|4.times{|k|s[k]+=v[j][k]/4.0}};s}
#1200 edges of 120cell at centres of faces of 600-cell. Search for pairs of tetrahedra with common face
x=f.map{|i|s=[];600.times{|j|s<<j if i==(i & g[j])};s}
#720 pentagonal faces, surrounding edges of 600-cell. Search for sets of 5 tetrahedra with common edge
y=e.map{|i|s=[];600.times{|j|s<<j if i==(i & g[j])};s}
#120 dodecahedral cells surrounding vertices of 600-cell. Search for sets of 20 tetrahedra with common vertex
z=(0..119).map{|i|s=[];600.times{|j|s<<j if [i]==([i] & g[j])};s}
#24-CELL
#24 vertices, a subset of the 600cell
o=v[0..23]
#96 edges, length 2, found by minimum distances between vertices
p=[]
24.times{|i|24.times{|j|
p<<[i,j] if i<j && ((v[i][0]-v[j][0])**2+(v[i][1]-v[j][1])**2+(v[i][2]-v[j][2])**2+(v[i][3]-v[j][3])**2)**0.5<2.1
}}
#96 triangles
#If 2 edges share a common vertex and the other 2 vertices form an edge in the list, it is a valid triangle.
q=[]
96.times{|i|96.times{|j|
q<< [p[i][0],p[i][1],p[j][1]] if i<j && p[i][0]==p[j][0] && p.index([p[i][1],p[j][1]])
}}
#24 cells. Calculates the centre of the cell and the 6 vertices nearest it
r=(0..23).map{|i|a,b=(-1)**i,(-1)**(i/2)
c=[[a,b,0,0],[a,0,b,0],[a,0,0,b],[0,a,b,0],[0,a,0,b],[0,0,a,b]][i/4]
s=[]
24.times{|j|t=v[j]
s<<j if (c[0]-t[0])**2+(c[1]-t[1])**2+(c[2]-t[2])**2+(c[3]-t[3])**2<=2
}
s}
https://en.wikipedia.org/wiki/600-cell
http://mathworld.wolfram.com/600-Cell.html
https://en.wikipedia.org/wiki/120-cell
http://mathworld.wolfram.com/120-Cell.html
https://en.wikipedia.org/wiki/24-cell
http://mathworld.wolfram.com/24-Cell.html
ตัวอย่างการใช้งานและเอาท์พุท
cell24 = polytope[[3,4,3]]
puts "vertices"
cell24[0].each{|i|p i}
puts "edges"
cell24[1].each{|i|p i}
puts "faces"
cell24[2].each{|i|p i}
puts "cells"
cell24[3].each{|i|p i}
vertices
[2, 0, 0, 0]
[0, 2, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 2]
[-2, 0, 0, 0]
[0, -2, 0, 0]
[0, 0, -2, 0]
[0, 0, 0, -2]
[1, 1, 1, 1]
[1, 1, 1, -1]
[1, 1, -1, 1]
[1, 1, -1, -1]
[1, -1, 1, 1]
[1, -1, 1, -1]
[1, -1, -1, 1]
[1, -1, -1, -1]
[-1, 1, 1, 1]
[-1, 1, 1, -1]
[-1, 1, -1, 1]
[-1, 1, -1, -1]
[-1, -1, 1, 1]
[-1, -1, 1, -1]
[-1, -1, -1, 1]
[-1, -1, -1, -1]
edges
[0, 8]
[0, 9]
[0, 10]
[0, 11]
[0, 12]
[0, 13]
[0, 14]
[0, 15]
[1, 8]
[1, 9]
[1, 10]
[1, 11]
[1, 16]
[1, 17]
[1, 18]
[1, 19]
[2, 8]
[2, 9]
[2, 12]
[2, 13]
[2, 16]
[2, 17]
[2, 20]
[2, 21]
[3, 8]
[3, 10]
[3, 12]
[3, 14]
[3, 16]
[3, 18]
[3, 20]
[3, 22]
[4, 16]
[4, 17]
[4, 18]
[4, 19]
[4, 20]
[4, 21]
[4, 22]
[4, 23]
[5, 12]
[5, 13]
[5, 14]
[5, 15]
[5, 20]
[5, 21]
[5, 22]
[5, 23]
[6, 10]
[6, 11]
[6, 14]
[6, 15]
[6, 18]
[6, 19]
[6, 22]
[6, 23]
[7, 9]
[7, 11]
[7, 13]
[7, 15]
[7, 17]
[7, 19]
[7, 21]
[7, 23]
[8, 9]
[8, 10]
[8, 12]
[8, 16]
[9, 11]
[9, 13]
[9, 17]
[10, 11]
[10, 14]
[10, 18]
[11, 15]
[11, 19]
[12, 13]
[12, 14]
[12, 20]
[13, 15]
[13, 21]
[14, 15]
[14, 22]
[15, 23]
[16, 17]
[16, 18]
[16, 20]
[17, 19]
[17, 21]
[18, 19]
[18, 22]
[19, 23]
[20, 21]
[20, 22]
[21, 23]
[22, 23]
faces
[0, 8, 9]
[0, 8, 10]
[0, 8, 12]
[0, 9, 11]
[0, 9, 13]
[0, 10, 11]
[0, 10, 14]
[0, 11, 15]
[0, 12, 13]
[0, 12, 14]
[0, 13, 15]
[0, 14, 15]
[1, 8, 9]
[1, 8, 10]
[1, 8, 16]
[1, 9, 11]
[1, 9, 17]
[1, 10, 11]
[1, 10, 18]
[1, 11, 19]
[1, 16, 17]
[1, 16, 18]
[1, 17, 19]
[1, 18, 19]
[2, 8, 9]
[2, 8, 12]
[2, 8, 16]
[2, 9, 13]
[2, 9, 17]
[2, 12, 13]
[2, 12, 20]
[2, 13, 21]
[2, 16, 17]
[2, 16, 20]
[2, 17, 21]
[2, 20, 21]
[3, 8, 10]
[3, 8, 12]
[3, 8, 16]
[3, 10, 14]
[3, 10, 18]
[3, 12, 14]
[3, 12, 20]
[3, 14, 22]
[3, 16, 18]
[3, 16, 20]
[3, 18, 22]
[3, 20, 22]
[4, 16, 17]
[4, 16, 18]
[4, 16, 20]
[4, 17, 19]
[4, 17, 21]
[4, 18, 19]
[4, 18, 22]
[4, 19, 23]
[4, 20, 21]
[4, 20, 22]
[4, 21, 23]
[4, 22, 23]
[5, 12, 13]
[5, 12, 14]
[5, 12, 20]
[5, 13, 15]
[5, 13, 21]
[5, 14, 15]
[5, 14, 22]
[5, 15, 23]
[5, 20, 21]
[5, 20, 22]
[5, 21, 23]
[5, 22, 23]
[6, 10, 11]
[6, 10, 14]
[6, 10, 18]
[6, 11, 15]
[6, 11, 19]
[6, 14, 15]
[6, 14, 22]
[6, 15, 23]
[6, 18, 19]
[6, 18, 22]
[6, 19, 23]
[6, 22, 23]
[7, 9, 11]
[7, 9, 13]
[7, 9, 17]
[7, 11, 15]
[7, 11, 19]
[7, 13, 15]
[7, 13, 21]
[7, 15, 23]
[7, 17, 19]
[7, 17, 21]
[7, 19, 23]
[7, 21, 23]
cells
[0, 1, 8, 9, 10, 11]
[1, 4, 16, 17, 18, 19]
[0, 5, 12, 13, 14, 15]
[4, 5, 20, 21, 22, 23]
[0, 2, 8, 9, 12, 13]
[2, 4, 16, 17, 20, 21]
[0, 6, 10, 11, 14, 15]
[4, 6, 18, 19, 22, 23]
[0, 3, 8, 10, 12, 14]
[3, 4, 16, 18, 20, 22]
[0, 7, 9, 11, 13, 15]
[4, 7, 17, 19, 21, 23]
[1, 2, 8, 9, 16, 17]
[2, 5, 12, 13, 20, 21]
[1, 6, 10, 11, 18, 19]
[5, 6, 14, 15, 22, 23]
[1, 3, 8, 10, 16, 18]
[3, 5, 12, 14, 20, 22]
[1, 7, 9, 11, 17, 19]
[5, 7, 13, 15, 21, 23]
[2, 3, 8, 12, 16, 20]
[3, 6, 10, 14, 18, 22]
[2, 7, 9, 13, 17, 21]
[6, 7, 11, 15, 19, 23]