Faces from a mesh: Difference between revisions
Content added Content deleted
(Added Go) |
|||
Line 77: | Line 77: | ||
Show your output here. |
Show your output here. |
||
=={{header|Go}}== |
|||
<lang go>package main |
|||
import ( |
|||
"fmt" |
|||
"sort" |
|||
) |
|||
// Check a slice contains a value. |
|||
func contains(s []int, f int) bool { |
|||
for _, e := range s { |
|||
if e == f { |
|||
return true |
|||
} |
|||
} |
|||
return false |
|||
} |
|||
// Assumes s1, s2 are of same length. |
|||
func sliceEqual(s1, s2 []int) bool { |
|||
for i := 0; i < len(s1); i++ { |
|||
if s1[i] != s2[i] { |
|||
return false |
|||
} |
|||
} |
|||
return true |
|||
} |
|||
// Reverses slice in place. |
|||
func reverse(s []int) { |
|||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { |
|||
s[i], s[j] = s[j], s[i] |
|||
} |
|||
} |
|||
// Check two perimeters are equal. |
|||
func perimEqual(p1, p2 []int) bool { |
|||
le := len(p1) |
|||
if le != len(p2) { |
|||
return false |
|||
} |
|||
for _, p := range p1 { |
|||
if !contains(p2, p) { |
|||
return false |
|||
} |
|||
} |
|||
// use copy to avoid mutating 'p1' |
|||
c := make([]int, le) |
|||
copy(c, p1) |
|||
for r := 0; r < 2; r++ { |
|||
for i := 0; i < le; i++ { |
|||
if sliceEqual(c, p2) { |
|||
return true |
|||
} |
|||
// do circular shift to right |
|||
t := c[le-1] |
|||
copy(c[1:], c[0:le-1]) |
|||
c[0] = t |
|||
} |
|||
// now process in opposite direction |
|||
reverse(c) |
|||
} |
|||
return false |
|||
} |
|||
type edge [2]int |
|||
// Translates a face to perimeter format. |
|||
func faceToPerim(face []edge) []int { |
|||
// use copy to avoid mutating 'face' |
|||
le := len(face) |
|||
if le == 0 { |
|||
return nil |
|||
} |
|||
edges := make([]edge, le) |
|||
for i := 0; i < le; i++ { |
|||
// check edge pairs are in correct order |
|||
if face[i][1] <= face[i][0] { |
|||
return nil |
|||
} |
|||
edges[i] = face[i] |
|||
} |
|||
// sort edges in ascending order |
|||
sort.Slice(edges, func(i, j int) bool { |
|||
if edges[i][0] != edges[j][0] { |
|||
return edges[i][0] < edges[j][0] |
|||
} |
|||
return edges[i][1] < edges[j][1] |
|||
}) |
|||
var perim []int |
|||
first, last := edges[0][0], edges[0][1] |
|||
perim = append(perim, first, last) |
|||
// remove first edge |
|||
copy(edges, edges[1:]) |
|||
edges = edges[0 : le-1] |
|||
le-- |
|||
outer: |
|||
for le > 0 { |
|||
for i, e := range edges { |
|||
found := false |
|||
if e[0] == last { |
|||
perim = append(perim, e[1]) |
|||
last, found = e[1], true |
|||
} else if e[1] == last { |
|||
perim = append(perim, e[0]) |
|||
last, found = e[0], true |
|||
} |
|||
if found { |
|||
// remove i'th edge |
|||
copy(edges[i:], edges[i+1:]) |
|||
edges = edges[0 : le-1] |
|||
le-- |
|||
if last == first { |
|||
if le == 0 { |
|||
break outer |
|||
} else { |
|||
return nil |
|||
} |
|||
} |
|||
continue outer |
|||
} |
|||
} |
|||
} |
|||
return perim[0 : len(perim)-1] |
|||
} |
|||
func main() { |
|||
fmt.Println("Perimeter format equality checks:") |
|||
areEqual := perimEqual([]int{8, 1, 3}, []int{1, 3, 8}) |
|||
fmt.Printf(" Q == R is %t\n", areEqual) |
|||
areEqual = perimEqual([]int{18, 8, 14, 10, 12, 17, 19}, []int{8, 14, 10, 12, 17, 19, 18}) |
|||
fmt.Printf(" U == V is %t\n", areEqual) |
|||
e := []edge{{7, 11}, {1, 11}, {1, 7}} |
|||
f := []edge{{11, 23}, {1, 17}, {17, 23}, {1, 11}} |
|||
g := []edge{{8, 14}, {17, 19}, {10, 12}, {10, 14}, {12, 17}, {8, 18}, {18, 19}} |
|||
h := []edge{{1, 3}, {9, 11}, {3, 11}, {1, 11}} |
|||
names := []string{"E", "F", "G", "H"} |
|||
fmt.Println("\nEdge to perimeter format translations:") |
|||
for i, face := range [][]edge{e, f, g, h} { |
|||
perim := faceToPerim(face) |
|||
if perim == nil { |
|||
fmt.Printf(" %s => Invalid edge format\n", names[i]) |
|||
} else { |
|||
fmt.Printf(" %s => %v\n", names[i], perim) |
|||
} |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
Perimeter format equality checks: |
|||
Q == R is true |
|||
U == V is true |
|||
Edge to perimeter format translations: |
|||
E => [1 7 11] |
|||
F => [1 11 23 17] |
|||
G => [8 14 10 12 17 19 18] |
|||
H => Invalid edge format |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |