Faces from a mesh: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(16 intermediate revisions by 11 users not shown)
Line 61:
 
;Task:
'''1.''' Write a routine to check if two perimeter formatted faces have the same perimeter. use Use it oto check if the following pairs of perimeters are the same:
<pre> Q: (8, 1, 3)
R: (1, 3, 8)
Line 76:
 
Show your output here.
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">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))</syntaxhighlight>
 
{{out}}
<pre>
Perimeter format equality checks:
Q == R
U == V
 
Edge to perimeter format translations:
E: [(1, 11), (7, 11), (1, 7)]
-> [1, 7, 11]
F: [(11, 23), (1, 17), (17, 23), (1, 11)]
-> [1, 11, 23, 17]
G: [(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)]
-> [8, 14, 10, 12, 17, 19, 18]
H: [(1, 3), (9, 11), (3, 11), (1, 11)]
-> >>>Error! Invalid edge format<<<
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
 
#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;
}
}
}
</syntaxhighlight>
{{ out }}
<pre>
PerimeterFormat equality checks:
[8, 1, 3] == [1, 3, 8]: true
[18, 8, 14, 10, 12, 17, 19] == [8, 14, 10, 12, 17, 19, 18]: true
 
EdgeFormat to PerimeterFormat conversions:
[(1, 11), (7, 11), (1, 7)] => [1, 7, 11]
[(11, 23), (1, 17), (17, 23), (1, 11)] => [11, 1, 17, 23]
[(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)] => [8, 18, 19, 17, 12, 10, 14]
[(1, 3), (9, 11), (3, 11), (1, 11)] has invalid edge format
</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 222 ⟶ 425:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 235 ⟶ 438:
G => [8 14 10 12 17 19 18]
H => Invalid edge format
</pre>
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">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)</syntaxhighlight>
 
First task.
 
<pre>λ> Perimeter [8,1,3] == Perimeter [1,3,8]
True
 
λ> Perimeter [8,1,3] == Perimeter [1,8,3]
True
 
λ> Perimeter [18,8,14,10,12,17,19] == Perimeter [8,14,10,12,17,19,18]
True
 
λ> Perimeter [18,8,14,10,12,17,19] == Perimeter [8,14,10,12,17,19]
False
 
λ> Perimeter [18,8,14,10,12,17,19] == Perimeter [8,14,10,12,17,18,19]
False</pre>
 
Second task
<pre>λ> toPerimeter (Edges [(1,11),(7,11),(1,7)])
Just (Perimeter [1,11,7])
 
λ> toPerimeter (Edges [(11,23),(1,17),(17,23),(1,11)])
Just (Perimeter [11,23,17,1])
 
λ> toPerimeter (Edges [(8,14),(17,19),(10,12),(10,14),(12,17),(8,18),(18,19)])
Just (Perimeter [8,14,10,12,17,19,18])
 
λ> toPerimeter (Edges [(1,3),(9,11),(3,11),(1,11)])
Nothing</pre>
 
=={{header|J}}==
First task:
<pre>
NB. construct a list of all rotations of one of the faces
NB. including all rotations of the reversed list.
NB. Find out if the other face is a member of this list.
 
NB. ,&:rotations -> append, but first enlist the rotations.
 
 
rotations=. |."0 1~ i.@#
reverse=: |.
same_perimeter=: e. (,&:rotations reverse)
 
(3, 1, 8)same_perimeter(8, 1, 3)
1
 
(18, 8, 14, 10, 12, 17, 19)same_perimeter(8, 14, 10, 12, 17, 19, 18)
1
</pre>
Secondly:
<syntaxhighlight lang="j">
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
)
</syntaxhighlight>
 
<pre>
boxdraw_j_ 0
 
]TESTS=: ([: < _2 ]\ ".);._2'{}'-.~0 :0
{(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)}
)
┌────┬─────┬─────┬────┐
│1 11│11 23│ 8 14│1 3│
│7 11│ 1 17│17 19│9 11│
│1 7│17 23│10 12│3 11│
│ │ 1 11│10 14│1 11│
│ │ │12 17│ │
│ │ │ 8 18│ │
│ │ │18 19│ │
└────┴─────┴─────┴────┘
 
 
 
edge_to_node ::('failure'"_)&.> TESTS
┌──────┬──────────┬───────────────────┬───────┐
│1 11 7│11 23 17 1│8 14 10 12 17 19 18│failure│
└──────┴──────────┴───────────────────┴───────┘
 
 
edge_to_node _1 {:: TESTS
|assertion failure: edge_to_node
| 2=#/.~,y['expect each node to appear twice'
</pre>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
 
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;
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
PerimeterFormat equality checks:
[8, 1, 3] == [1, 3, 8]: true
[18, 8, 14, 10, 12, 17, 19] == [8, 14, 10, 12, 17, 19, 18]: true
 
EdgeFormat to PerimeterFormat conversions:
[(1, 11), (7, 11), (1, 7)] => [1, 7, 11]
[(11, 23), (1, 17), (17, 23), (1, 11)] => [11, 1, 17, 23]
[(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)] => [8, 18, 19, 17, 12, 10, 14]
[(1, 3), (9, 11), (3, 11), (1, 11)] has invalid edge format
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">iseq(f, g) = any(n -> f == circshift(g, n), 1:length(g))
 
function toface(evec)
Line 273 ⟶ 745:
println(toface(face))
end
</langsyntaxhighlight>{{out}}
<pre>
Faces are equivalent.
Line 282 ⟶ 754:
Invalid edges vector: Tuple{Int64,Int64}[(1, 3), (9, 11), (3, 11), (1, 11)]
</pre>
 
=={{header|Koka}}==
<syntaxhighlight lang="koka">
alias perimeter = list<int>
alias face = (char, perimeter)
alias edge = (int, int)
 
fun isSame(p1: perimeter, p2: perimeter, noSwitch: list<int> = []): div bool
match (p1, p2)
([], []) -> True
(Cons(x1, xs1), Cons(x2, xs2)) | x1 == x2 -> isSame(xs1, xs2)
_ ->
match p2
Nil -> False
Cons(x2, xs2) ->
if noSwitch.any(fn(x') x' == x2) then False else p1.isSame(xs2 ++ [x2], Cons(x2, noSwitch))
 
fun show(f: face)
val (c, p) = f
c.core/show ++ " " ++ p.core/show
 
fun findRemove(l: list<a>, acc: ctx<list<a>>, pred: (a) -> bool): maybe<(a, list<a>)>
match l
[] -> Nothing
Cons(x, xs) -> match pred(x)
True -> Just((x, acc ++. xs))
False -> findRemove(xs, acc ++ ctx Cons(x, _), pred)
 
fun toPerimeter(search: int, edges: list<edge>, acc: ctx<perimeter>): <div,exn> perimeter
match edges
[] -> acc ++. Cons(search, Nil) // Assume the search matches the first edge's missing
_ -> match edges.findRemove(ctx _, fn((a, b)) a == search || b == search)
Just(((a, b), xs')) -> if search == a then
toPerimeter(b, xs', acc ++ ctx Cons(a, _))
else
toPerimeter(a, xs', acc ++ ctx Cons(b, _))
Nothing -> throw("Cannot find the next edge for " ++ search.show ++ " current perimeter is " ++ (acc ++. Nil).show ++ " and the rest of the edges are: " ++ edges.show-list(fn(s) s.show-tuple(show, show)))
 
fun main()
val 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]))]
fp.foreach() fn((f1, f2))
val same = f1.snd.isSame(f2.snd)
print(f1.show ++ (if same then " is " else " is not ") ++ "the same as " ++ f2.show ++ "\n")
val 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)])]
fe.foreach() fn((f, edges))
match edges
[] -> ()
Cons((initX, _), edges') ->
val p = toPerimeter(initX, edges', ctx _)
print(f.show ++ " perimeter is " ++ p.show ++ "\n")
</syntaxhighlight>
{{out}}
<pre>
'P' [8,1,3] is the same as 'R' [1,3,8]
'U' [18,8,14,10,12,17,19] is the same as 'V' [8,14,10,12,17,19,18]
'E' perimeter is [1,7,11]
'F' perimeter is [11,1,17,23]
'G' perimeter is [8,18,19,17,12,10,14]
uncaught exception: Cannot find the next edge for 9 current perimeter is [1,11] and the rest of the edges are: [(3,11)]
</pre>
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">-- 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(","))</syntaxhighlight>
{{out}}
<pre>pfeq(Q,R): true
pfeq(U,V): true
ef2pf(E): 1,11,7
ef2pf(F): 11,23,17,1
ef2pf(G): 8,14,10,12,17,19,18
ef2pf(H): failed to convert edge format to perimeter format</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">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</syntaxhighlight>
 
{{out}}
<pre>Perimeter comparison:
P(8, 1, 3) is same as R(1, 3, 8)
U(18, 8, 14, 10, 12, 17, 19) is same as V(8, 14, 10, 12, 17, 19, 18)
 
Conversion from edge to perimeter format:
E: (1, 11, 7)
F: (1, 17, 23, 11)
G: (18, 8, 14, 10, 12, 17, 19)
H: Invalid edge list</pre>
 
=={{header|Perl}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 341 ⟶ 1,047:
[[1, 3], [9, 11], [3, 11], [1, 11]]) {
say show($_) . ' ==> (' . (join ' ', edge_to_periphery(@$_) or 'Invalid edge format') . ')'
}</langsyntaxhighlight>
{{out}}
<pre>Perimeter format equality checks:
Line 354 ⟶ 1,060:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function perequiv(sequence a, b)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
-- Works by aligning and rotating in one step, so theoretically much faster on massive sets.
<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>
-- (ahem, faster than multiple rotates, index-only loops would obviously be even faster...)
<span style="color: #000080;font-style:italic;">-- Works by aligning and rotating in one step, so theoretically much faster on massive sets.
bool res = (length(a)==length(b))
-- (ahem, faster than multiple rotates, index-only loops would obviously be even faster...)</span>
if res and length(a)>0 then
<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>
integer k = find(a[1],b)
<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>
if k=0 then
<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>
res = false
<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>
else
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
-- align with a (ie make b[1]==a[1], by
<span style="color: #008080;">else</span>
-- rotating b k places in one operation)
<span style="color: #000080;font-style:italic;">-- align with a (ie make b[1]==a[1], by
b = b[k..$]&b[1..k-1]
if a!=-- rotating b thenk 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>
-- eg {8,3,4,5} <=> {8,5,4,3}, ie
<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>
-- rotate *and* keep in alignment.
<span style="color: #000080;font-style:italic;">-- eg {8,3,4,5} &lt;=&gt; {8,5,4,3}, ie
b[2..$] = reverse(b[2..$])
res =-- (a==b)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>
end if
<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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- return res
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return {"false","true"}[res+1]
<span style="color: #000080;font-style:italic;">-- return res</span>
end function
<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>
function edge2peri(sequence edges)
sequence was = edges, res = {}
<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>
string error = ""
<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>
integer lnk = 0
<span style="color: #004080;">string</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
if length(edges)<2 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">lnk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
error = "too short"
<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>
else
<span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"too short"</span>
-- edges = sort(edges) -- (see note below)
<span style="color: #008080;">else</span>
res = edges[1]
<span style="color: #000080;font-style:italic;">-- edges = sort(deep_copy(edges)) -- (see note below)</span>
edges = edges[2..$]
<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>
lnk = res[2]
<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>
while length(edges) and error="" do
<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>
bool found = false
<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>
for i=1 to length(edges) do
<span style="color: #004080;">bool</span> <span style="color: #000000;">found</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
integer k = find(lnk,edges[i])
<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>
if k then
<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>
lnk = edges[i][3-k]
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span> <span style="color: #008080;">then</span>
edges[i..i] = {}
<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>
if edges={} then
<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>
if lnk!=res[1] then error = "oh dear" end if
<span style="color: #008080;">if</span> <span style="color: #000000;">edges</span><span style="color: #0000FF;">={}</span> <span style="color: #008080;">then</span>
else
<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>
if find(lnk,res) then error = "oops" end if
<span res &style="color: lnk#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>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">lnk</span>
found = true
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
exit
<span style="color: #000000;">found</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
end if
<span style="color: #008080;">exit</span>
end for
if not found then error =<span style="badcolor: link#008080;">end</span> exit<span endstyle="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end while
<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>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
if length(error) then res = {error,res,lnk,edges,was} end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return res
<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>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant ptests = {{{8, 1, 3}, {1, 3, 8}},
{{18, 8, 14, 10, 12, 17, 19}, {8, 14, 10, 12, 17, 19, 18}},
<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>
-- (check our results below against Go etc)
<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>
{{1,11,7},{1,7,11}},
<span style="color: #000080;font-style:italic;">-- (check our results below against Go etc)</span>
{{11,23,17,1},{1,11,23,17}}}
<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>
for i=1 to length(ptests) do
<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>
sequence {p,q} = ptests[i]
<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>
printf(1,"%v equivalent to %v: %s\n",{p,q,perequiv(p,q)})
<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>
end for
<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>
constant etests = {{{1, 11}, {7, 11}, {1, 7}},
{{11, 23}, {1, 17}, {17, 23}, {1, 11}},
<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>
{{8, 14}, {17, 19}, {10, 12}, {10, 14}, {12, 17}, {8, 18}, {18, 19}},
<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>
{{1, 3}, {9, 11}, {3, 11}, {1, 11}}}
<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>
for i=1 to length(etests) do
<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>
printf(1,"%v\n",{edge2peri(etests[i])})
<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>
end for</lang>
<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>
<!--</syntaxhighlight>-->
{{out}}
(second part matches Julia/Perl: un-comment that sort above to match Go/Python/zkl)
Line 444 ⟶ 1,153:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">def perim_equal(p1, p2):
# Cheap tests first
if len(p1) != len(p2) or set(p1) != set(p2):
Line 493 ⟶ 1,202:
}
for name, edges in edge_d.items():
print(f" {name}: {edges}\n -> {edge_to_periphery(edges)}")</langsyntaxhighlight>
 
{{out}}
Line 514 ⟶ 1,223:
{{works with|Rakudo|2019.11}}
 
<syntaxhighlight lang="raku" perl6line>sub check-equivalence ($a, $b) { so $a.Bag eqv $b.Bag }
 
sub edge-to-periphery (@a is copy) {
Line 554 ⟶ 1,263:
.gist.print;
say " ==> ({.&edge-to-periphery || 'Invalid edge format'})";
}</langsyntaxhighlight>
{{out}}
<pre>Perimeter format equality checks:
Line 565 ⟶ 1,274:
((8 14) (17 19) (10 12) (10 14) (12 17) (8 18) (18 19)) ==> (8 14 10 12 17 19 18)
((1 3) (9 11) (3 11) (1 11)) ==> (Invalid edge format)</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-sort}}
{{libheader|Wren-seq}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">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)
}
}</syntaxhighlight>
 
{{out}}
<pre>
Perimeter format equality checks:
Q == R is true
U == V is true
 
Edge to perimeter format translations:
E => [1, 7, 11]
E => [1, 11, 23, 17]
E => [8, 14, 10, 12, 17, 19, 18]
E => Invalid edge format
</pre>
 
=={{header|zkl}}==
{{trans|Python}}
<langsyntaxhighlight lang="zkl">fcn perimSame(p1, p2){
if(p1.len() != p2.len()) return(False);
False == p1.filter1('wrap(p){ (not p2.holds(p)) })
Line 584 ⟶ 1,417:
}
p[0,-1] // last element not part of result
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">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) ) );
Line 602 ⟶ 1,435:
 
fcn pp(a){ a.concat(", ","(",")") }
fcn ppp(edges){ pp(edges.apply(pp)) }</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits