Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Faces-from-a-mesh/00-META.yaml
Normal file
2
Task/Faces-from-a-mesh/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Faces_from_a_mesh
|
||||
76
Task/Faces-from-a-mesh/00-TASK.txt
Normal file
76
Task/Faces-from-a-mesh/00-TASK.txt
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
A [[wp:Polygon mesh|mesh]] defining a surface has uniquely numbered vertices, and named,
|
||||
simple-polygonal faces described usually by an ordered list of edge numbers
|
||||
going around the face,
|
||||
|
||||
|
||||
For example:
|
||||
[https://drive.google.com/file/d/1qNS_L0LGIKhoo-gmBLlyDGECtjp9l7x8/view External image of two faces]<br>
|
||||
Rough textual version without edges:
|
||||
<pre>
|
||||
|
||||
1
|
||||
17
|
||||
7 A
|
||||
B
|
||||
|
||||
11
|
||||
23
|
||||
|
||||
</pre>
|
||||
|
||||
* A is the triangle (1, 11, 7), or equally (7, 11, 1), going anti-clockwise, or
|
||||
any of all the rotations of those ordered vertices.
|
||||
<pre> 1
|
||||
|
||||
7 A
|
||||
|
||||
|
||||
11</pre>
|
||||
|
||||
* B is the four-sided face (1, 17, 23, 11), or equally (23, 17, 1, 11) or any
|
||||
of their rotations.
|
||||
<pre>1
|
||||
17
|
||||
|
||||
B
|
||||
|
||||
11
|
||||
23</pre>
|
||||
|
||||
Let's call the above the '''perimeter format''' as it traces around the perimeter.
|
||||
|
||||
;A second format:
|
||||
A separate algorithm returns polygonal faces consisting of a face name and an unordered
|
||||
set of edge definitions for each face.
|
||||
* A single edge is described by the vertex numbers at its two ends, always in
|
||||
ascending order.
|
||||
* All edges for the face are given, but in an undefined order.
|
||||
|
||||
For example face A could be described by the edges (1, 11), (7, 11), and (1, 7)
|
||||
(The order of each vertex number in an edge is ascending, but the order in
|
||||
which the edges are stated is arbitrary).
|
||||
|
||||
Similarly face B could be described by the edges (11, 23), (1, 17), (17, 23),
|
||||
and (1, 11) in arbitrary order of the edges.
|
||||
|
||||
Let's call this second format the '''edge format'''.
|
||||
|
||||
|
||||
|
||||
;Task:
|
||||
'''1.''' Write a routine to check if two perimeter formatted faces have the same perimeter. Use it to check if the following pairs of perimeters are the same:
|
||||
<pre> Q: (8, 1, 3)
|
||||
R: (1, 3, 8)
|
||||
|
||||
U: (18, 8, 14, 10, 12, 17, 19)
|
||||
V: (8, 14, 10, 12, 17, 19, 18)
|
||||
</pre>
|
||||
'''2.''' Write a routine and use it to transform the following faces from edge to perimeter format.
|
||||
<pre> E: {(1, 11), (7, 11), (1, 7)}
|
||||
F: {(11, 23), (1, 17), (17, 23), (1, 11)}
|
||||
G: {(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)}
|
||||
H: {(1, 3), (9, 11), (3, 11), (1, 11)}
|
||||
</pre>
|
||||
|
||||
Show your output here.
|
||||
|
||||
48
Task/Faces-from-a-mesh/11l/faces-from-a-mesh.11l
Normal file
48
Task/Faces-from-a-mesh/11l/faces-from-a-mesh.11l
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
F perim_equal(p1, =p2)
|
||||
I p1.len != p2.len | Set(p1) != Set(p2)
|
||||
R 0B
|
||||
I any((0 .< p1.len).map(n -> @p2 == (@p1[n ..] [+] @p1[0 .< n])))
|
||||
R 1B
|
||||
p2 = reversed(p2)
|
||||
R any((0 .< p1.len).map(n -> @p2 == (@p1[n ..] [+] @p1[0 .< n])))
|
||||
|
||||
F edge_to_periphery(e)
|
||||
V edges = sorted(e)
|
||||
[Int] p
|
||||
I !edges.empty
|
||||
p = [edges[0][0], edges[0][1]]
|
||||
edges.pop(0)
|
||||
V last = I !p.empty {p.last} E -1
|
||||
L !edges.empty
|
||||
L(ij) edges
|
||||
V (i, j) = ij
|
||||
I i == last
|
||||
p.append(j)
|
||||
last = j
|
||||
edges.pop(L.index)
|
||||
L.break
|
||||
E I j == last
|
||||
p.append(i)
|
||||
last = i
|
||||
edges.pop(L.index)
|
||||
L.break
|
||||
L.was_no_break
|
||||
R ‘>>>Error! Invalid edge format<<<’
|
||||
R String(p[0 .< (len)-1])
|
||||
|
||||
print(‘Perimeter format equality checks:’)
|
||||
L(eq_check) [(‘Q’, [8, 1, 3],
|
||||
‘R’, [1, 3, 8]),
|
||||
(‘U’, [18, 8, 14, 10, 12, 17, 19],
|
||||
‘V’, [8, 14, 10, 12, 17, 19, 18])]
|
||||
V (n1, p1, n2, p2) = eq_check
|
||||
V eq = I perim_equal(p1, p2) {‘==’} E ‘!=’
|
||||
print(‘ ’n1‘ ’eq‘ ’n2)
|
||||
|
||||
print("\nEdge to perimeter format translations:")
|
||||
V edge_d = [‘E’ = [(1, 11), (7, 11), (1, 7)],
|
||||
‘F’ = [(11, 23), (1, 17), (17, 23), (1, 11)],
|
||||
‘G’ = [(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)],
|
||||
‘H’ = [(1, 3), (9, 11), (3, 11), (1, 11)]]
|
||||
L(name, edges) edge_d
|
||||
print(‘ ’name‘: ’edges"\n -> "edge_to_periphery(edges))
|
||||
117
Task/Faces-from-a-mesh/C++/faces-from-a-mesh.cpp
Normal file
117
Task/Faces-from-a-mesh/C++/faces-from-a-mesh.cpp
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
typedef std::pair<int32_t, int32_t> Edge;
|
||||
|
||||
std::string to_string(const int32_t& value) {
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
std::string to_string(const Edge& edge) {
|
||||
return "(" + std::to_string(edge.first) + ", " + std::to_string(edge.second) + ")";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string vector_to_string(const std::vector<T>& list) {
|
||||
std::string result = "[";
|
||||
for ( uint64_t i = 0; i < list.size() - 1; ++i ) {
|
||||
result += to_string(list[i]) + ", ";
|
||||
}
|
||||
result += to_string(list.back()) + "]";
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_same_face(const std::vector<int32_t>& list_1, const std::vector<int32_t>& list_2) {
|
||||
if ( list_1.size() != list_2.size() || list_1.empty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int32_t> copy_2(list_2);
|
||||
for ( int32_t i = 0; i < 2; ++i ) {
|
||||
int32_t start;
|
||||
if ( auto iterator = std::find(copy_2.begin(), copy_2.end(), list_1.front()); iterator != copy_2.end() ) {
|
||||
start = std::distance(copy_2.begin(), iterator);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
std::vector<int32_t> test(copy_2.begin() + start, copy_2.end());
|
||||
test.insert(test.end(), copy_2.begin(), copy_2.begin() + start);//addAll(copyTwo.subList(0, start));
|
||||
if ( list_1 == test ) {
|
||||
return true;
|
||||
}
|
||||
std::reverse(copy_2.begin(), copy_2.end());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int32_t> to_perimeter_format_face(const std::vector<Edge>& edge_format_face) {
|
||||
if ( edge_format_face.empty() ) {
|
||||
return std::vector<int32_t>();
|
||||
}
|
||||
|
||||
std::vector<Edge> edges(edge_format_face);
|
||||
std::vector<int32_t> result;
|
||||
Edge first_edge = edges.front();
|
||||
edges.erase(edges.begin());
|
||||
int next_vertex = first_edge.first;
|
||||
result.push_back(next_vertex);
|
||||
|
||||
while ( ! edges.empty() ) {
|
||||
int32_t index = -1;
|
||||
for ( Edge edge : edges ) {
|
||||
if ( edge.first == next_vertex || edge.second == next_vertex ) {
|
||||
if ( auto iterator = std::find(edges.begin(), edges.end(), edge); iterator != edges.end() ) {
|
||||
index = std::distance(edges.begin(), iterator);
|
||||
}
|
||||
next_vertex = ( next_vertex == edge.first ) ? edge.second : edge.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( index == -1 ) {
|
||||
return std::vector<int32_t>();
|
||||
}
|
||||
result.push_back(next_vertex);
|
||||
edges.erase(edges.begin() + index);
|
||||
}
|
||||
|
||||
if ( next_vertex != first_edge.second ) {
|
||||
return std::vector<int32_t>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main() {
|
||||
const std::vector<int32_t> perimeter_format_q = { 8, 1, 3 };
|
||||
const std::vector<int32_t> perimeter_format_r = { 1, 3, 8 };
|
||||
const std::vector<int32_t> perimeter_format_u = { 18, 8, 14, 10, 12, 17, 19 };
|
||||
const std::vector<int32_t> perimeter_format_v = { 8, 14, 10, 12, 17, 19, 18 };
|
||||
|
||||
const std::vector<Edge> edge_format_e = { Edge(1, 11), Edge(7, 11), Edge(1, 7) };
|
||||
const std::vector<Edge> edge_format_f = { Edge(11, 23), Edge(1, 17), Edge(17, 23), Edge(1, 11) };
|
||||
const std::vector<Edge> edge_format_g =
|
||||
{ Edge(8, 14), Edge(17, 19), Edge(10, 12), Edge(10, 14), Edge(12, 17), Edge(8, 18), Edge(18, 19) };
|
||||
const std::vector<Edge> edge_format_h = { Edge(1, 3), Edge(9, 11), Edge(3, 11), Edge(1, 11) };
|
||||
|
||||
std::cout << "PerimeterFormat equality checks:" << std::endl;
|
||||
bool same_face = is_same_face(perimeter_format_q, perimeter_format_r);
|
||||
std::cout << vector_to_string(perimeter_format_q) << " == "
|
||||
<< vector_to_string(perimeter_format_r) << ": " << std::boolalpha << same_face << std::endl;
|
||||
same_face = is_same_face(perimeter_format_u, perimeter_format_v);
|
||||
std::cout << vector_to_string(perimeter_format_u) << " == "
|
||||
<< vector_to_string(perimeter_format_v) << ": " << std::boolalpha << same_face << std::endl;
|
||||
|
||||
std::cout << "\nEdgeFormat to PerimeterFormat conversions:" << std::endl;
|
||||
std::vector<std::vector<Edge>> edge_format_faces = { edge_format_e, edge_format_f, edge_format_g, edge_format_h };
|
||||
for ( std::vector<Edge> edge_format_face : edge_format_faces ) {
|
||||
std::vector<int32_t> perimeter_format_face = to_perimeter_format_face(edge_format_face);
|
||||
if ( perimeter_format_face.empty() ) {
|
||||
std::cout << vector_to_string(edge_format_face) << " has invalid edge format" << std::endl;
|
||||
} else {
|
||||
std::cout << vector_to_string(edge_format_face) << " => "
|
||||
<< vector_to_string(perimeter_format_face) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
145
Task/Faces-from-a-mesh/Go/faces-from-a-mesh.go
Normal file
145
Task/Faces-from-a-mesh/Go/faces-from-a-mesh.go
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
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}}
|
||||
fmt.Println("\nEdge to perimeter format translations:")
|
||||
for i, face := range [][]edge{e, f, g, h} {
|
||||
perim := faceToPerim(face)
|
||||
if perim == nil {
|
||||
fmt.Printf(" %c => Invalid edge format\n", i + 'E')
|
||||
} else {
|
||||
fmt.Printf(" %c => %v\n", i + 'E', perim)
|
||||
}
|
||||
}
|
||||
}
|
||||
43
Task/Faces-from-a-mesh/Haskell/faces-from-a-mesh.hs
Normal file
43
Task/Faces-from-a-mesh/Haskell/faces-from-a-mesh.hs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import Data.List (find, delete, (\\))
|
||||
import Control.Applicative ((<|>))
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
newtype Perimeter a = Perimeter [a]
|
||||
deriving Show
|
||||
|
||||
instance Eq a => Eq (Perimeter a) where
|
||||
Perimeter p1 == Perimeter p2 =
|
||||
null (p1 \\ p2)
|
||||
&& ((p1 `elem` zipWith const (iterate rotate p2) p1)
|
||||
|| Perimeter p1 == Perimeter (reverse p2))
|
||||
|
||||
rotate lst = zipWith const (tail (cycle lst)) lst
|
||||
|
||||
toEdges :: Ord a => Perimeter a -> Maybe (Edges a)
|
||||
toEdges (Perimeter ps)
|
||||
| allDifferent ps = Just . Edges $ zipWith ord ps (tail (cycle ps))
|
||||
| otherwise = Nothing
|
||||
where
|
||||
ord a b = if a < b then (a, b) else (b, a)
|
||||
|
||||
allDifferent [] = True
|
||||
allDifferent (x:xs) = all (x /=) xs && allDifferent xs
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
newtype Edges a = Edges [(a, a)]
|
||||
deriving Show
|
||||
|
||||
instance Eq a => Eq (Edges a) where
|
||||
e1 == e2 = toPerimeter e1 == toPerimeter e2
|
||||
|
||||
toPerimeter :: Eq a => Edges a -> Maybe (Perimeter a)
|
||||
toPerimeter (Edges ((a, b):es)) = Perimeter . (a :) <$> go b es
|
||||
where
|
||||
go x rs
|
||||
| x == a = return []
|
||||
| otherwise = do
|
||||
p <- find ((x ==) . fst) rs <|> find ((x ==) . snd) rs
|
||||
let next = if fst p == x then snd p else fst p
|
||||
(x :) <$> go next (delete p rs)
|
||||
12
Task/Faces-from-a-mesh/J/faces-from-a-mesh.j
Normal file
12
Task/Faces-from-a-mesh/J/faces-from-a-mesh.j
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
edge_to_node=: 3 :0
|
||||
assert. 2 = #/.~ , y [ 'expect each node to appear twice'
|
||||
oel=. 1 2 {. y
|
||||
Y=. }. y
|
||||
while. # Y do.
|
||||
i =. <. -: 1 i.~ , Y (e."1) {: oel
|
||||
assert. 0 < # i [ 'isolated edge detected'
|
||||
oel =. oel , i { Y
|
||||
Y =. i ({. , (}.~ >:)~) Y
|
||||
end.
|
||||
~. , oel
|
||||
)
|
||||
109
Task/Faces-from-a-mesh/Java/faces-from-a-mesh.java
Normal file
109
Task/Faces-from-a-mesh/Java/faces-from-a-mesh.java
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public final class FacesFromMesh {
|
||||
|
||||
public static void main(String[] aArgs) {
|
||||
final List<Integer> perimeterFormatQ = Arrays.asList( 8, 1, 3 );
|
||||
final List<Integer> perimeterFormatR = Arrays.asList( 1, 3, 8 );
|
||||
final List<Integer> perimeterFormatU = Arrays.asList( 18, 8, 14, 10, 12, 17, 19 );
|
||||
final List<Integer> perimeterFormatV = Arrays.asList( 8, 14, 10, 12, 17, 19, 18 );
|
||||
|
||||
final List<Edge> edgeFormatE = Arrays.asList( new Edge(1, 11), new Edge(7, 11), new Edge(1, 7) );
|
||||
final List<Edge> edgeFormatF =
|
||||
Arrays.asList( new Edge(11, 23), new Edge(1, 17), new Edge(17, 23), new Edge(1, 11) );
|
||||
final List<Edge> edgeFormatG = Arrays.asList( new Edge(8, 14), new Edge(17, 19),
|
||||
new Edge(10, 12), new Edge(10, 14), new Edge(12, 17), new Edge(8, 18), new Edge(18, 19) );
|
||||
final List<Edge> edgeFormatH =
|
||||
Arrays.asList( new Edge(1, 3), new Edge(9, 11), new Edge(3, 11), new Edge(1, 11) );
|
||||
|
||||
System.out.println("PerimeterFormat equality checks:");
|
||||
boolean sameFace = isSameFace(perimeterFormatQ, perimeterFormatR);
|
||||
System.out.println(perimeterFormatQ + " == " + perimeterFormatR + ": " + sameFace);
|
||||
sameFace = isSameFace(perimeterFormatU, perimeterFormatV);
|
||||
System.out.println(perimeterFormatU + " == " + perimeterFormatV + ": " + sameFace);
|
||||
|
||||
System.out.println(System.lineSeparator() + "EdgeFormat to PerimeterFormat conversions:");
|
||||
List<List<Edge>> edgeFormatFaces = List.of( edgeFormatE, edgeFormatF, edgeFormatG, edgeFormatH );
|
||||
for ( List<Edge> edgeFormatFace : edgeFormatFaces ) {
|
||||
List<Integer> perimeterFormatFace = toPerimeterFormatFace(edgeFormatFace);
|
||||
if ( perimeterFormatFace.isEmpty() ) {
|
||||
System.out.println(edgeFormatFace + " has invalid edge format");
|
||||
} else {
|
||||
System.out.println(edgeFormatFace + " => " + perimeterFormatFace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSameFace(List<Integer> aOne, List<Integer> aTwo) {
|
||||
if ( aOne.size() != aTwo.size() || aOne.isEmpty() ||
|
||||
! new HashSet<Integer>(aOne).equals( new HashSet<Integer>(aTwo) )) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> copyTwo = new ArrayList<Integer>(aTwo);
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
int start = copyTwo.indexOf(aOne.get(0));
|
||||
List<Integer> test = new ArrayList<Integer>(copyTwo.subList(start, copyTwo.size()));
|
||||
test.addAll(copyTwo.subList(0, start));
|
||||
if ( aOne.equals(test) ) {
|
||||
return true;
|
||||
}
|
||||
Collections.reverse(copyTwo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<Integer> toPerimeterFormatFace(List<Edge> aEdgeFormatFace) {
|
||||
if ( aEdgeFormatFace.isEmpty() ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<Edge> edges = new ArrayList<Edge>(aEdgeFormatFace);
|
||||
List<Integer> result = new ArrayList<Integer>();
|
||||
Edge firstEdge = edges.remove(0);
|
||||
int nextVertex = firstEdge.first;
|
||||
result.add(nextVertex);
|
||||
|
||||
while ( ! edges.isEmpty() ) {
|
||||
int index = -1;
|
||||
for ( Edge edge : edges ) {
|
||||
if ( edge.first == nextVertex || edge.second == nextVertex ) {
|
||||
index = edges.indexOf(edge);
|
||||
nextVertex = ( nextVertex == edge.first ) ? edge.second : edge.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( index == -1 ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
result.add(nextVertex);
|
||||
edges.remove(index);
|
||||
}
|
||||
|
||||
if ( nextVertex != firstEdge.second ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class Edge {
|
||||
|
||||
public Edge(int aFirst, int aSecond) {
|
||||
first = aFirst;
|
||||
second = aSecond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + first + ", " + second + ")";
|
||||
}
|
||||
|
||||
private int first, second;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
35
Task/Faces-from-a-mesh/Julia/faces-from-a-mesh.julia
Normal file
35
Task/Faces-from-a-mesh/Julia/faces-from-a-mesh.julia
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
iseq(f, g) = any(n -> f == circshift(g, n), 1:length(g))
|
||||
|
||||
function toface(evec)
|
||||
try
|
||||
ret, edges = collect(evec[1]), copy(evec[2:end])
|
||||
while !isempty(edges)
|
||||
i = findfirst(x -> ret[end] == x[1] || ret[end] == x[2], edges)
|
||||
push!(ret, ret[end] == edges[i][1] ? edges[i][2] : edges[i][1])
|
||||
deleteat!(edges, i)
|
||||
end
|
||||
return ret[1:end-1]
|
||||
catch
|
||||
println("Invalid edges vector: $evec")
|
||||
exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
const faces1 = [
|
||||
[[8, 1, 3], [1, 3, 8]],
|
||||
[[18, 8, 14, 10, 12, 17, 19], [8, 14, 10, 12, 17, 19, 18]]
|
||||
]
|
||||
|
||||
const faces2 = [
|
||||
[(1, 11), (7, 11), (1, 7)], [(11, 23), (1, 17), (17, 23), (1, 11)],
|
||||
[(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)],
|
||||
[(1, 3), (9, 11), (3, 11), (1, 11)]
|
||||
]
|
||||
|
||||
for faces in faces1
|
||||
println("Faces are ", iseq(faces[1], faces[2]) ? "" : "not ", "equivalent.")
|
||||
end
|
||||
|
||||
for face in faces2
|
||||
println(toface(face))
|
||||
end
|
||||
57
Task/Faces-from-a-mesh/Lua/faces-from-a-mesh.lua
Normal file
57
Task/Faces-from-a-mesh/Lua/faces-from-a-mesh.lua
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
-- support
|
||||
function T(t) return setmetatable(t, {__index=table}) end
|
||||
table.eql = function(t,u) if #t~=#u then return false end for i=1,#t do if t[i]~=u[i] then return false end end return true end
|
||||
table.rol = function(t,n) local s=T{} for i=1,#t do s[i]=t[(i+n-1)%#t+1] end return s end
|
||||
table.rev = function(t) local s=T{} for i=1,#t do s[#t-i+1]=t[i] end return s end
|
||||
|
||||
-- 1
|
||||
function pfeq(pf1, pf2)
|
||||
if #pf1 ~= #pf2 then return false end -- easy case
|
||||
for w = 0,1 do -- exhaustive cases
|
||||
local pfw = pf1 -- w:winding
|
||||
if w==1 then pfw=pfw:rev() end
|
||||
for r = 0,#pfw do
|
||||
local pfr = pfw -- r:rotate
|
||||
if r>0 then pfr=pfr:rol(r) end
|
||||
if pf2:eql(pfr) then return true end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
Q = T{8, 1, 3}
|
||||
R = T{1, 3, 8}
|
||||
U = T{18, 8, 14, 10, 12, 17, 19}
|
||||
V = T{8, 14, 10, 12, 17, 19, 18}
|
||||
print("pfeq(Q,R): ", pfeq(Q, R))
|
||||
print("pfeq(U,V): ", pfeq(U, V))
|
||||
|
||||
-- 2
|
||||
function ef2pf(ef)
|
||||
local pf, hse = T{}, T{} -- hse:hash of sorted edges
|
||||
for i,e in ipairs(ef) do table.sort(e) hse[e]=e end
|
||||
local function nexte(e)
|
||||
if not e then return ef[1] end
|
||||
for k,v in pairs(hse) do
|
||||
if e[2]==v[1] then return v end
|
||||
if e[2]==v[2] then v[1],v[2]=v[2],v[1] return v end
|
||||
end
|
||||
end
|
||||
local e = nexte()
|
||||
while e do
|
||||
pf[#pf+1] = e[1]
|
||||
hse[e] = nil
|
||||
e = nexte(e)
|
||||
end
|
||||
if #pf ~= #ef then pf=T{"failed to convert edge format to perimeter format"} end
|
||||
return pf
|
||||
end
|
||||
|
||||
E = {{1, 11}, {7, 11}, {1, 7}}
|
||||
F = {{11, 23}, {1, 17}, {17, 23}, {1, 11}}
|
||||
G = {{8, 14}, {17, 19}, {10, 12}, {10, 14}, {12, 17}, {8, 18}, {18, 19}}
|
||||
H = {{1, 3}, {9, 11}, {3, 11}, {1, 11}}
|
||||
print("ef2pf(E): ", ef2pf(E):concat(","))
|
||||
print("ef2pf(F): ", ef2pf(F):concat(","))
|
||||
print("ef2pf(G): ", ef2pf(G):concat(","))
|
||||
print("ef2pf(H): ", ef2pf(H):concat(","))
|
||||
91
Task/Faces-from-a-mesh/Nim/faces-from-a-mesh.nim
Normal file
91
Task/Faces-from-a-mesh/Nim/faces-from-a-mesh.nim
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import algorithm, strutils
|
||||
|
||||
type
|
||||
Perimeter = seq[int]
|
||||
Face = tuple[name: char; perimeter: Perimeter]
|
||||
Edge = tuple[first, last: int]
|
||||
|
||||
const None = -1 # No point.
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func isSame(p1, p2: Perimeter): bool =
|
||||
## Return "true" if "p1" and "p2" represent the same face.
|
||||
|
||||
if p1.len != p2.len: return false
|
||||
|
||||
for p in p1:
|
||||
if p notin p2: return false
|
||||
|
||||
var start = p2.find(p1[0])
|
||||
if p1 == p2[start..^1] & p2[0..<start]:
|
||||
return true
|
||||
|
||||
let p3 = reversed(p2)
|
||||
start = p3.find(p1[0])
|
||||
if p1 == p3[start..^1] & p3[0..<start]:
|
||||
return true
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func `$`(perimeter: Perimeter): string =
|
||||
## Convert a perimeter to a string.
|
||||
'(' & perimeter.join(", ") & ')'
|
||||
|
||||
func `$`(face: Face): string =
|
||||
## Convert a perimeter formatted face to a string.
|
||||
face.name & $face.perimeter
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
func toPerimeter(edges: seq[Edge]): Perimeter =
|
||||
## Convert a list of edges to perimeter representation.
|
||||
## Return an empty perimeter if the list of edges doesn’t represent a face.
|
||||
|
||||
var edges = edges
|
||||
let firstEdge = edges.pop() # First edge taken in account.
|
||||
var nextPoint = firstEdge.first # Next point to search in remaining edges.
|
||||
result.add(nextpoint)
|
||||
|
||||
while edges.len > 0:
|
||||
# Search an edge.
|
||||
var idx = None
|
||||
for i, e in edges:
|
||||
if e.first == nextPoint or e.last == nextPoint:
|
||||
idx = i
|
||||
nextPoint = if nextpoint == e.first: e.last else: e.first
|
||||
break
|
||||
if idx == None:
|
||||
return @[] # No edge found containing "newPoint".
|
||||
|
||||
# Add next point to perimeter and remove the edge.
|
||||
result.add(nextPoint)
|
||||
edges.del(idx)
|
||||
|
||||
# Check that last added point is the expected one.
|
||||
if nextPoint != firstEdge.last:
|
||||
return @[]
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
when isMainModule:
|
||||
|
||||
# List of pairs of perimeter formatted faces to compare.
|
||||
const FP = [(('P', @[8, 1, 3]), ('R', @[1, 3, 8])),
|
||||
(('U', @[18, 8, 14, 10, 12, 17, 19]), ('V', @[8, 14, 10, 12, 17, 19, 18]))]
|
||||
|
||||
echo "Perimeter comparison:"
|
||||
for (p1, p2) in FP:
|
||||
echo p1, if isSame(p1[1], p2[1]): " is same as " else: "is not same as", p2
|
||||
|
||||
# List of edge formatted faces.
|
||||
const FE = {'E': @[(1, 11), (7, 11), (1, 7)],
|
||||
'F': @[(11, 23), (1, 17), (17, 23), (1, 11)],
|
||||
'G': @[(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)],
|
||||
'H': @[(1, 3), (9, 11), (3, 11), (1, 11)]}
|
||||
|
||||
echo ""
|
||||
echo "Conversion from edge to perimeter format:"
|
||||
for (faceName, edges) in FE:
|
||||
let perimeter = edges.toPerimeter()
|
||||
echo faceName, ": ", if perimeter.len == 0: "Invalid edge list" else: $perimeter
|
||||
57
Task/Faces-from-a-mesh/Perl/faces-from-a-mesh.pl
Normal file
57
Task/Faces-from-a-mesh/Perl/faces-from-a-mesh.pl
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use Set::Scalar;
|
||||
use Set::Bag;
|
||||
use Storable qw(dclone);
|
||||
|
||||
sub show { my($pts) = @_; my $p='( '; $p .= '(' . join(' ',@$_) . ') ' for @$pts; $p.')' }
|
||||
|
||||
sub check_equivalence {
|
||||
my($a, $b) = @_;
|
||||
Set::Scalar->new(@$a) == Set::Scalar->new(@$b)
|
||||
}
|
||||
|
||||
sub edge_to_periphery {
|
||||
my $a = dclone \@_;
|
||||
|
||||
my $bag_a = Set::Bag->new;
|
||||
for my $p (@$a) {
|
||||
$bag_a->insert( @$p[0] => 1);
|
||||
$bag_a->insert( @$p[1] => 1);
|
||||
}
|
||||
2 != @$bag_a{$_} and return 0 for keys %$bag_a;
|
||||
|
||||
my $b = shift @$a;
|
||||
while ($#{$a} > 0) {
|
||||
for my $k (0..$#{$a}) {
|
||||
my $v = @$a[$k];
|
||||
if (@$v[0] == @$b[-1]) {
|
||||
push @$b, @$v[1];
|
||||
splice(@$a,$k,1);
|
||||
last
|
||||
} elsif (@$v[1] == @$b[-1]) {
|
||||
push @$b, @$v[0];
|
||||
splice(@$a,$k,1);
|
||||
last
|
||||
}
|
||||
}
|
||||
}
|
||||
@$b;
|
||||
}
|
||||
|
||||
say 'Perimeter format equality checks:';
|
||||
for ([[8, 1, 3], [1, 3, 8]],
|
||||
[[18, 8, 14, 10, 12, 17, 19], [8, 14, 10, 12, 17, 19, 18]]) {
|
||||
my($a, $b) = @$_;
|
||||
say '(' . join(', ', @$a) . ') equivalent to (' . join(', ', @$b) . ')? ',
|
||||
check_equivalence($a, $b) ? 'True' : 'False';
|
||||
}
|
||||
|
||||
say "\nEdge to perimeter format translations:";
|
||||
for ([[1, 11], [7, 11], [1, 7]],
|
||||
[[11, 23], [1, 17], [17, 23], [1, 11]],
|
||||
[[8, 14], [17, 19], [10, 12], [10, 14], [12, 17], [8, 18], [18, 19]],
|
||||
[[1, 3], [9, 11], [3, 11], [1, 11]]) {
|
||||
say show($_) . ' ==> (' . (join ' ', edge_to_periphery(@$_) or 'Invalid edge format') . ')'
|
||||
}
|
||||
79
Task/Faces-from-a-mesh/Phix/faces-from-a-mesh.phix
Normal file
79
Task/Faces-from-a-mesh/Phix/faces-from-a-mesh.phix
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">perequiv</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- Works by aligning and rotating in one step, so theoretically much faster on massive sets.
|
||||
-- (ahem, faster than multiple rotates, index-only loops would obviously be even faster...)</span>
|
||||
<span style="color: #004080;">bool</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)==</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000080;font-style:italic;">-- align with a (ie make b[1]==a[1], by
|
||||
-- rotating b k places in one operation)</span>
|
||||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">..$]&</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">b</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000080;font-style:italic;">-- eg {8,3,4,5} <=> {8,5,4,3}, ie
|
||||
-- rotate *and* keep in alignment.</span>
|
||||
<span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$])</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">==</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000080;font-style:italic;">-- return res</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"false"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"true"</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">res</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">edge2peri</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">was</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">lnk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"too short"</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000080;font-style:italic;">-- edges = sort(deep_copy(edges)) -- (see note below)</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #000000;">edges</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
|
||||
<span style="color: #000000;">lnk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">error</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">bool</span> <span style="color: #000000;">found</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">lnk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">3</span><span style="color: #0000FF;">-</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">edges</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">={}</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">lnk</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"oh dear"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"oops"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">lnk</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">found</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">found</span> <span style="color: #008080;">then</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"bad link"</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">error</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">error</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edges</span><span style="color: #0000FF;">,</span><span style="color: #000000;">was</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">ptests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #000080;font-style:italic;">-- (check our results below against Go etc)</span>
|
||||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">}}}</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ptests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ptests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%v equivalent to %v: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">perequiv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">etests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">23</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">17</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">}}}</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">etests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">edge2peri</span><span style="color: #0000FF;">(</span><span style="color: #000000;">etests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
50
Task/Faces-from-a-mesh/Python/faces-from-a-mesh.py
Normal file
50
Task/Faces-from-a-mesh/Python/faces-from-a-mesh.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
def perim_equal(p1, p2):
|
||||
# Cheap tests first
|
||||
if len(p1) != len(p2) or set(p1) != set(p2):
|
||||
return False
|
||||
if any(p2 == (p1[n:] + p1[:n]) for n in range(len(p1))):
|
||||
return True
|
||||
p2 = p2[::-1] # not inplace
|
||||
return any(p2 == (p1[n:] + p1[:n]) for n in range(len(p1)))
|
||||
|
||||
def edge_to_periphery(e):
|
||||
edges = sorted(e)
|
||||
p = list(edges.pop(0)) if edges else []
|
||||
last = p[-1] if p else None
|
||||
while edges:
|
||||
for n, (i, j) in enumerate(edges):
|
||||
if i == last:
|
||||
p.append(j)
|
||||
last = j
|
||||
edges.pop(n)
|
||||
break
|
||||
elif j == last:
|
||||
p.append(i)
|
||||
last = i
|
||||
edges.pop(n)
|
||||
break
|
||||
else:
|
||||
#raise ValueError(f'Invalid edge format: {e}')
|
||||
return ">>>Error! Invalid edge format<<<"
|
||||
return p[:-1]
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('Perimeter format equality checks:')
|
||||
for eq_check in [
|
||||
{ 'Q': (8, 1, 3),
|
||||
'R': (1, 3, 8)},
|
||||
{ 'U': (18, 8, 14, 10, 12, 17, 19),
|
||||
'V': (8, 14, 10, 12, 17, 19, 18)} ]:
|
||||
(n1, p1), (n2, p2) = eq_check.items()
|
||||
eq = '==' if perim_equal(p1, p2) else '!='
|
||||
print(' ', n1, eq, n2)
|
||||
|
||||
print('\nEdge to perimeter format translations:')
|
||||
edge_d = {
|
||||
'E': {(1, 11), (7, 11), (1, 7)},
|
||||
'F': {(11, 23), (1, 17), (17, 23), (1, 11)},
|
||||
'G': {(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)},
|
||||
'H': {(1, 3), (9, 11), (3, 11), (1, 11)}
|
||||
}
|
||||
for name, edges in edge_d.items():
|
||||
print(f" {name}: {edges}\n -> {edge_to_periphery(edges)}")
|
||||
41
Task/Faces-from-a-mesh/Raku/faces-from-a-mesh.raku
Normal file
41
Task/Faces-from-a-mesh/Raku/faces-from-a-mesh.raku
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
sub check-equivalence ($a, $b) { so $a.Bag eqv $b.Bag }
|
||||
|
||||
sub edge-to-periphery (@a is copy) {
|
||||
return Nil unless @a.List.Bag.values.all == 2;
|
||||
my @b = @a.shift.flat;
|
||||
while @a > 1 {
|
||||
for @a.kv -> $k, $v {
|
||||
if $v[0] == @b.tail {
|
||||
@b.push: $v[1];
|
||||
@a.splice($k,1);
|
||||
last
|
||||
}
|
||||
elsif $v[1] == @b.tail {
|
||||
@b.push: $v[0];
|
||||
@a.splice($k,1);
|
||||
last
|
||||
}
|
||||
}
|
||||
}
|
||||
@b
|
||||
}
|
||||
|
||||
say 'Perimeter format equality checks:';
|
||||
|
||||
for (8, 1, 3), (1, 3, 8),
|
||||
(18, 8, 14, 10, 12, 17, 19), (8, 14, 10, 12, 17, 19, 18)
|
||||
-> $a, $b {
|
||||
say "({$a.join: ', '}) equivalent to ({$b.join: ', '})? ",
|
||||
check-equivalence($a, $b)
|
||||
}
|
||||
|
||||
say "\nEdge to perimeter format translations:";
|
||||
|
||||
for ((1, 11), (7, 11), (1, 7)),
|
||||
((11, 23), (1, 17), (17, 23), (1, 11)),
|
||||
((8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)),
|
||||
((1, 3), (9, 11), (3, 11), (1, 11))
|
||||
{
|
||||
.gist.print;
|
||||
say " ==> ({.&edge-to-periphery || 'Invalid edge format'})";
|
||||
}
|
||||
105
Task/Faces-from-a-mesh/Wren/faces-from-a-mesh.wren
Normal file
105
Task/Faces-from-a-mesh/Wren/faces-from-a-mesh.wren
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import "./sort" for Sort
|
||||
import "./seq" for Lst
|
||||
import "./fmt" for Fmt
|
||||
|
||||
// Check two perimeters are equal.
|
||||
var perimEqual = Fn.new { |p1, p2|
|
||||
var le = p1.count
|
||||
if (le != p2.count) return false
|
||||
for (p in p1) {
|
||||
if (!p2.contains(p)) return false
|
||||
}
|
||||
// use copy to avoid mutating 'p1'
|
||||
var c = p1.toList
|
||||
for (r in 0..1) {
|
||||
for (i in 0...le) {
|
||||
if (Lst.areEqual(c, p2)) return true
|
||||
// do circular shift to right
|
||||
Lst.rshift(c)
|
||||
}
|
||||
// now process in opposite direction
|
||||
Lst.reverse(c) // reverses 'c' in place
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var faceToPerim = Fn.new { |face|
|
||||
// use copy to avoid mutating 'face'
|
||||
var le = face.count
|
||||
if (le == 0) return []
|
||||
var edges = List.filled(le, null)
|
||||
for (i in 0...le) {
|
||||
// check edge pairs are in correct order
|
||||
if (face[i][1] <= face[i][0]) return []
|
||||
edges[i] = [face[i][0], face[i][1]]
|
||||
}
|
||||
// sort edges in ascending order
|
||||
var cmp = Fn.new { |e1, e2|
|
||||
if (e1[0] != e2[0]) {
|
||||
return (e1[0] - e2[0]).sign
|
||||
}
|
||||
return (e1[1] - e2[1]).sign
|
||||
}
|
||||
Sort.insertion(edges, cmp)
|
||||
var first = edges[0][0]
|
||||
var last = edges[0][1]
|
||||
var perim = [first, last]
|
||||
// remove first edge
|
||||
edges.removeAt(0)
|
||||
le = le - 1
|
||||
while (le > 0) {
|
||||
var i = 0
|
||||
var outer = false
|
||||
var cont = false
|
||||
for (e in edges) {
|
||||
var found = false
|
||||
if (e[0] == last) {
|
||||
perim.add(e[1])
|
||||
last = e[1]
|
||||
found = true
|
||||
} else if (e[1] == last) {
|
||||
perim.add(e[0])
|
||||
last = e[0]
|
||||
found = true
|
||||
}
|
||||
if (found) {
|
||||
// remove i'th edge
|
||||
edges.removeAt(i)
|
||||
le = le - 1
|
||||
if (last == first) {
|
||||
if (le == 0) {
|
||||
outer = true
|
||||
break
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
cont = true
|
||||
break
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
if (outer && !cont) break
|
||||
}
|
||||
return perim[0..-2]
|
||||
}
|
||||
|
||||
System.print("Perimeter format equality checks:")
|
||||
var areEqual = perimEqual.call([8, 1, 3], [1, 3, 8])
|
||||
System.print(" Q == R is %(areEqual)")
|
||||
areEqual = perimEqual.call([18, 8, 14, 10, 12, 17, 19], [8, 14, 10, 12, 17, 19, 18])
|
||||
System.print(" U == V is %(areEqual)")
|
||||
var e = [[7, 11], [1, 11], [1, 7]]
|
||||
var f = [[11, 23], [1, 17], [17, 23], [1, 11]]
|
||||
var g = [[8, 14], [17, 19], [10, 12], [10, 14], [12, 17], [8, 18], [18, 19]]
|
||||
var h = [[1, 3], [9, 11], [3, 11], [1, 11]]
|
||||
System.print("\nEdge to perimeter format translations:")
|
||||
var i = 0
|
||||
for (face in [e, f, g, h]) {
|
||||
var perim = faceToPerim.call(face)
|
||||
if (perim.isEmpty) {
|
||||
Fmt.print(" $c => Invalid edge format", i + 69) // 'E' is ASCII 69
|
||||
} else {
|
||||
Fmt.print(" $c => $n", i + 69, perim)
|
||||
}
|
||||
}
|
||||
17
Task/Faces-from-a-mesh/Zkl/faces-from-a-mesh-1.zkl
Normal file
17
Task/Faces-from-a-mesh/Zkl/faces-from-a-mesh-1.zkl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
fcn perimSame(p1, p2){
|
||||
if(p1.len() != p2.len()) return(False);
|
||||
False == p1.filter1('wrap(p){ (not p2.holds(p)) })
|
||||
}
|
||||
|
||||
fcn edge_to_periphery(faces){
|
||||
edges:=faces.copy().sort(fcn(a,b){ if(a[0]!=b[0]) a[0]<b[0] else a[1]<b[1] });
|
||||
p,last := ( if(edges) edges.pop(0).copy() else T ), ( p and p[-1] or Void );
|
||||
while(edges){
|
||||
foreach i,j in (edges){
|
||||
if (i==last){ p.append( last=j ); edges.del(__iWalker.idx); break; }
|
||||
else if(j==last){ p.append( last=i ); edges.del(__iWalker.idx); break; }
|
||||
}
|
||||
fallthrough{ return(">>>Error! Invalid edge format<<<") }
|
||||
}
|
||||
p[0,-1] // last element not part of result
|
||||
}
|
||||
18
Task/Faces-from-a-mesh/Zkl/faces-from-a-mesh-2.zkl
Normal file
18
Task/Faces-from-a-mesh/Zkl/faces-from-a-mesh-2.zkl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
println("Perimeter format equality checks:");
|
||||
ps:=T( T( T(8,1,3), T(1,3,8) ),
|
||||
T( T(18, 8, 14, 10, 12, 17, 19), T(8, 14, 10, 12, 17, 19, 18) ) );
|
||||
foreach p1,p2 in (ps)
|
||||
{ println(pp(p1), " equivalent to ", pp(p2), "? ", perimSame(p1,p2)) }
|
||||
|
||||
println("\nEdge to perimeter format translations:");
|
||||
edge_d:=T(
|
||||
T(T( 1, 11), T( 7, 11), T( 1, 7) ),
|
||||
T(T(11, 23), T( 1, 17), T(17, 23), T( 1, 11) ),
|
||||
T(T( 8, 14), T(17, 19), T(10, 12), T(10, 14), T(12, 17), T(8, 18), T(18, 19) ),
|
||||
T(T( 1, 3), T( 9, 11), T( 3, 11), T( 1, 11) ),
|
||||
);
|
||||
foreach edges in (edge_d)
|
||||
{ println(ppp(edges), " --> ", edge_to_periphery(edges)) }
|
||||
|
||||
fcn pp(a){ a.concat(", ","(",")") }
|
||||
fcn ppp(edges){ pp(edges.apply(pp)) }
|
||||
Loading…
Add table
Add a link
Reference in a new issue