Last letter-first letter: Difference between revisions

Added Easylang
(Added zkl)
(Added Easylang)
 
(73 intermediate revisions by 30 users not shown)
Line 1:
{{task}}
A certain childrens game involves starting with a word in a particular category. Each participant in turn says a word, but that word must begin with the final letter of the previous word. Once a word has been given, it cannot be repeated. If an opponent cannot give a word in the category, they fall out of the game. For example, with "animals" as the category,
 
A certain children's game involves starting with a word in a particular category.   Each participant in turn says a word, but that word must begin with the final letter of the previous word.   Once a word has been given, it cannot be repeated.   If an opponent cannot give a word in the category, they fall out of the game.
<pre>Child 1: dog
 
 
For example, with &nbsp; "animals" &nbsp; as the category,
<pre>
Child 1: dog
Child 2: goldfish
Child 1: hippopotamus
Line 9 ⟶ 13:
</pre>
 
;Task Description
Take the following selection of 70 English Pokemon names (extracted from [[wp:List of Pokémon|Wikipedia's list of Pokemon]]) and generate the/a sequence with the highest possible number of Pokemon names where the subsequent name starts with the final letter of the preceding name. No Pokemon name is to be repeated.
 
;Task:
<pre>audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
Take the following selection of 70 English Pokemon names &nbsp; (extracted from &nbsp; [[wp:List of Pokémon|Wikipedia's list of Pokemon]]) &nbsp; and generate the/a sequence with the highest possible number of Pokemon names where the subsequent name starts with the final letter of the preceding name.
 
No Pokemon name is to be repeated.
 
<pre>
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
Line 19 ⟶ 27:
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask</pre>
</pre>
 
 
Extra brownie points for dealing with the full list of 646 names.
Extra brownie points for dealing with the full list of &nbsp; 646 &nbsp; names.
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F order_words(words)
DefaultDict[Char, Set[String]] byfirst
L(word) words
byfirst[word[0]].add(word)
R byfirst
 
F linkfirst(&byfirst; sofar)
assert(!sofar.empty)
V chmatch = sofar.last.last
V options = byfirst[chmatch] - Set(sofar)
 
I options.empty
R sofar
E
V alternatives = options.map(word -> linkfirst(&@byfirst, @sofar [+] [word]))
R max(alternatives, key' s -> s.len)
 
F llfl(words)
V byfirst = order_words(words)
R max((words.map(word -> linkfirst(&@byfirst, [word]))), key' s -> s.len)
 
V pokemon_str = ‘audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask’
V pokemon = pokemon_str.split((‘ ’, "\n"))
V l = llfl(pokemon)
L(i) (0 .< l.len).step(8)
print(l[i .< i + 8].join(‘ ’))
print(l.len)</syntaxhighlight>
 
{{out}}
<pre>
machamp petilil landorus scrafty yamask kricketune emboar registeel
loudred darmanitan nosepass simisear relicanth heatmor rufflet trapinch
haxorus seaking girafarig gabite exeggcute emolga audino
23
</pre>
 
=={{header|Ada}}==
 
<langsyntaxhighlight Adalang="ada">with Ada.Containers.Indefinite_Vectors, Ada.Text_IO;
 
procedure Lalefile is
Line 103 ⟶ 160:
Ada.Text_IO.Put_Line("One such path:");
Write(Best);
end Lalefile;</langsyntaxhighlight>
 
Output:<pre>Processing a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,
Line 131 ⟶ 188:
emolga
audino</pre>
 
=={{header|BaCon}}==
Naive implementation showing the algorithm.
<syntaxhighlight lang="freebasic">all$ = "audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon " \
"cresselia croagunk darmanitan deino emboar emolga exeggcute gabite " \
"girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan " \
"kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine " \
"nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2 " \
"porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking " \
"sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko " \
"tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask"
 
SUB check(list$, rest$)
 
LOCAL x
 
FOR x = 1 TO AMOUNT(rest$)
IF RIGHT$(list$, 1) = LEFT$(TOKEN$(rest$, x), 1) THEN check(APPEND$(list$, 0, TOKEN$(rest$, x)), DEL$(rest$, x))
NEXT
 
IF AMOUNT(list$) > total THEN
total = AMOUNT(list$)
result$ = list$
END IF
 
END SUB
 
FOR z = 1 TO AMOUNT(all$)
CALL check(TOKEN$(all$, z), DEL$(all$,z))
NEXT
 
PRINT total, ": ", result$
 
PRINT NL$, "Speed: ", TIMER, " msecs."</syntaxhighlight>
{{out}}
<pre>
23: machamp petilil landorus scrafty yamask kricketune emboar registeel loudred darmanitan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite exeggcute emolga audino
 
Speed: 662734 msecs.
</pre>
Optimized implementation. The idea is to quantify the equations.
<syntaxhighlight lang="freebasic">all$ = "audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon " \
"cresselia croagunk darmanitan deino emboar emolga exeggcute gabite " \
"girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan " \
"kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine " \
"nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2 " \
"porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking " \
"sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko " \
"tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask"
 
SPLIT all$ TO name$ SIZE MaxSize
 
DECLARE start, end, used, result ARRAY MaxSize
 
FOR y = 0 TO MaxSize-1
start[y] = ASC(LEFT$(name$[y], 1))
end[y] = ASC(RIGHT$(name$[y], 1))
used[y] = -1
NEXT
 
FOR i = 0 TO MaxSize-1
used[i] = 0
CALL check(used, i, 1)
used[i] = -1
NEXT
 
PRINT maxtotal, ": ";
FOR a = 0 TO maxtotal-1
FOR y = 0 TO MaxSize-1
IF result[y] = a THEN PRINT name$[y]," ";
NEXT
NEXT
 
PRINT NL$, "Speed: ", TIMER, " msecs."
 
SUB check(ya[], ultim, nr)
 
LOCAL x
 
FOR x = 0 TO MaxSize-1
IF end[ultim] = start[x] AND ya[x] = -1 THEN
ya[x] = nr
CALL check(ya, x, nr+1)
ya[x] = -1
END IF
 
IF nr > maxtotal THEN
maxtotal = nr
OPTION MEMTYPE long
COPY ya TO result SIZE MaxSize
END IF
NEXT
 
END SUB
</syntaxhighlight>
{{out}}
<pre>
23: machamp petilil landorus scrafty yamask kricketune emboar registeel loudred darmanitan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite exeggcute emolga audino
 
Speed: 818 msecs.
</pre>
 
=={{header|BASIC256}}==
<langsyntaxhighlight lang="basic256">dim names$(1)
names$ = { "audino", "bagon", "baltoy", "banette", "bidoof", "braviary", "bronzor", "carracosta", "charmeleon", "cresselia", "croagunk", "darmanitan", "deino", "emboar", "emolga", "exeggcute", "gabite", "girafarig", "gulpin", "haxorus", "heatmor", "heatran", "ivysaur", "jellicent", "jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba", "loudred", "lumineon", "lunatone", "machamp", "magnezone", "mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu", "pinsir", "poliwrath", "poochyena", "porygon2", "porygonz", "registeel", "relicanth", "remoraid", "rufflet", "sableye", "scolipede", "scrafty", "seaking", "sealeo", "silcoon", "simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga", "trapinch", "treecko", "tyrogue", "vigoroth", "vulpix", "wailord", "wartortle", "whismur", "wingull", "yamask" }
 
Line 189 ⟶ 348:
index[b] = t
end subroutine
</syntaxhighlight>
</lang>
 
Output:
Line 203 ⟶ 362:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> DIM names$(69)
names$() = "audino", "bagon", "baltoy", "banette", \
\ "bidoof", "braviary", "bronzor", "carracosta", "charmeleon", \
Line 253 ⟶ 412:
ENDIF
NEXT
ENDPROC</langsyntaxhighlight>
'''Output:'''
<pre>
Line 286 ⟶ 445:
=={{header|Bracmat}}==
===Naive===
<langsyntaxhighlight lang="bracmat">( audino bagon baltoy banette bidoof braviary bronzor
carracosta charmeleon cresselia croagunk darmanitan deino
emboar emolga exeggcute gabite girafarig gulpin haxorus
Line 328 ⟶ 487:
& lalefile$(.!names)
& out$("Length:" !max "Sequence:" !sequence)
);</langsyntaxhighlight>
Output (read from bottom to top):
<pre> Length:
Line 381 ⟶ 540:
The optimized version is about 4.5 times faster than the naive version.
 
<langsyntaxhighlight lang="bracmat">( audino bagon baltoy banette bidoof braviary bronzor
carracosta charmeleon cresselia croagunk darmanitan deino
emboar emolga exeggcute gabite girafarig gulpin haxorus
Line 440 ⟶ 599:
& lalefile$(.!names)
& out$("Length:" !max "Sequence:" !sequence)
);</langsyntaxhighlight>
Output (read from bottom to top):
<pre> Length:
Line 471 ⟶ 630:
=={{header|C}}==
From the D version.
<langsyntaxhighlight lang="c">#include <stdlib.h>
#include <string.h>
#include <stdio.h>
Line 584 ⟶ 743:
 
return 0;
}</langsyntaxhighlight>
Output:
<pre>Maximum path length: 23
Line 597 ⟶ 756:
===Approximate===
For dealing with full list (646 names), here's an approximate method. Names are restricted to begin and end with a lower case letter, so for example in my input file "porygon2" is written as "porygon-two". It finds some chains with 300-odd length for 646 names, and found a chain with 23 for the 70 names (by luck, that is), and since it's basically a one-pass method, running time is next to none. C99 code.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 792 ⟶ 951:
printf("longest found: %d\n", best);
return 0;
}</langsyntaxhighlight>output<syntaxhighlight lang="text">read 646 names
307: voltorb breloom magikarp palpito...
308: voltorb bayleef forretress swinub b...
Line 800 ⟶ 959:
322: voltorb beldum mandibuzz zekrom murk...
323: voltorb breloom mandibuzz zekr...
longest found: 323</langsyntaxhighlight>
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 867 ⟶ 1,026:
}
}
}</langsyntaxhighlight><pre>machamp
petilil
landorus
Line 888 ⟶ 1,047:
emolga
audino</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <iostream>
#include <string>
#include <vector>
 
struct last_letter_first_letter {
size_t max_path_length = 0;
size_t max_path_length_count = 0;
std::vector<std::string> max_path_example;
 
void search(std::vector<std::string>& names, size_t offset) {
if (offset > max_path_length) {
max_path_length = offset;
max_path_length_count = 1;
max_path_example.assign(names.begin(), names.begin() + offset);
} else if (offset == max_path_length) {
++max_path_length_count;
}
char last_letter = names[offset - 1].back();
for (size_t i = offset, n = names.size(); i < n; ++i) {
if (names[i][0] == last_letter) {
names[i].swap(names[offset]);
search(names, offset + 1);
names[i].swap(names[offset]);
}
}
}
 
void find_longest_chain(std::vector<std::string>& names) {
max_path_length = 0;
max_path_length_count = 0;
max_path_example.clear();
for (size_t i = 0, n = names.size(); i < n; ++i) {
names[i].swap(names[0]);
search(names, 1);
names[i].swap(names[0]);
}
}
};
 
int main() {
std::vector<std::string> names{"audino", "bagon", "baltoy", "banette",
"bidoof", "braviary", "bronzor", "carracosta", "charmeleon",
"cresselia", "croagunk", "darmanitan", "deino", "emboar",
"emolga", "exeggcute", "gabite", "girafarig", "gulpin",
"haxorus", "heatmor", "heatran", "ivysaur", "jellicent",
"jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba",
"loudred", "lumineon", "lunatone", "machamp", "magnezone",
"mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu",
"pinsir", "poliwrath", "poochyena", "porygon2", "porygonz",
"registeel", "relicanth", "remoraid", "rufflet", "sableye",
"scolipede", "scrafty", "seaking", "sealeo", "silcoon",
"simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga",
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix",
"wailord", "wartortle", "whismur", "wingull", "yamask"};
last_letter_first_letter solver;
solver.find_longest_chain(names);
std::cout << "Maximum path length: " << solver.max_path_length << '\n';
std::cout << "Paths of that length: " << solver.max_path_length_count << '\n';
std::cout << "Example path of that length:\n ";
for (size_t i = 0, n = solver.max_path_example.size(); i < n; ++i) {
if (i > 0 && i % 7 == 0)
std::cout << "\n ";
else if (i > 0)
std::cout << ' ';
std::cout << solver.max_path_example[i];
}
std::cout << '\n';
}</syntaxhighlight>
 
{{out}}
<pre>
Maximum path length: 23
Paths of that length: 1248
Example path of that length:
machamp petilil landorus scrafty yamask kricketune emboar
registeel loudred darmanitan nosepass simisear relicanth heatmor
rufflet trapinch haxorus seaking girafarig gabite exeggcute
emolga audino
</pre>
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">(ns rosetta-code.last-letter-first-letter
(:require clojure.string))
 
(defn by-first-letter
"Returns a map from letters to a set of words that start with that letter"
[words]
(into {} (map (fn [[k v]]
[k (set v)]))
(group-by first words)))
 
(defn longest-path-from
"Find a longest path starting at word, using only words-by-first-letter for successive words.
Returns a pair of [length list-of-words] to describe the path."
[word words-by-first-letter]
(let [words-without-word (update words-by-first-letter (first word)
disj word)
next-words (words-without-word (last word))]
(if (empty? next-words)
[1 [word]]
(let [sub-paths (map #(longest-path-from % words-without-word) next-words)
[length words-of-path] (apply max-key first sub-paths)]
[(inc length) (cons word words-of-path)]))))
 
(defn longest-word-chain
"Find a longest path among the words in word-list, by performing a longest path search
starting at each word in the list."
[word-list]
(let [words-by-letter (by-first-letter word-list)]
(apply max-key first
(pmap #(longest-path-from % words-by-letter)
word-list))))
 
(defn word-list-from-file [file-name]
(let [contents (slurp file-name)
words (clojure.string/split contents #"[ \n]")]
(filter #(not (empty? %)) words)))
 
(time (longest-word-chain (word-list-from-file "pokemon.txt")))</syntaxhighlight>
Evaluating the last line:
<syntaxhighlight lang="clojure">"Elapsed time: 2867.337816 msecs"
[23
("machamp"
"pinsir"
"relicanth"
"heatmor"
"registeel"
"landorus"
"seaking"
"girafarig"
"gabite"
"exeggcute"
"emboar"
"rufflet"
"trapinch"
"haxorus"
"simisear"
"remoraid"
"darmanitan"
"nosepass"
"scrafty"
"yamask"
"kricketune"
"emolga"
"audino")]</syntaxhighlight>
It initially ran in about 5 seconds, then I changed <code>map</code> to <code>pmap</code> (parallel map) in <code>longest-word-chain</code>.
This gave a nice speedup for a dual core laptop; the speedup for parallel searches was over 3x on a server.
 
=={{header|Common Lisp}}==
Pretty brute force here. Takes a couple of seconds to run.
<langsyntaxhighlight lang="lisp">;;; return all the words that start with an initial letter
 
(defun filter-with-init (words init)
Line 1,008 ⟶ 1,316:
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask)))
 
(setf *path* (best-path *words*))</langsyntaxhighlight>
Output:<syntaxhighlight lang="text">("MACHAMP" "PETILIL" "LANDORUS" "SCRAFTY" "YAMASK" "KRICKETUNE" "EMBOAR" "REGISTEEL"
"LOUDRED" "DARMANITAN" "NOSEPASS" "SIMISEAR" "RELICANTH" "HEATMOR" "RUFFLET"
"TRAPINCH" "HAXORUS" "SEAKING" "GIRAFARIG" "GABITE" "EXEGGCUTE" "EMOLGA" "AUDINO")</langsyntaxhighlight>
 
=={{header|D}}==
===Simple Version===
Modified from the Go version:
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string;
 
void searchtrySwap(string[] items, ref string item, in intsize_t len, ref string[] longest) pure {
pure nothrow @safe {
swap(items[len], item);
search(items, len + 1, longest);
swap(items[len], item);
}
 
void search(string[] items, in size_t len, ref string[] longest)
pure nothrow @safe {
if (len > longest.length)
longest = items[0 .. len].dup;
immutable lastChar = items[len - 1][$ - 1];
foreach (ref item; items[len .. $])
if (item[0] == lastChar) {
swaptrySwap(items[len], item, len, longest);
search(items, len + 1, longest);
swap(items[len], item);
}
}
 
void main() @safe {
auto pokemon = "audino bagon baltoy banette bidoof braviary
bronzor carracosta charmeleon cresselia croagunk darmanitan deino
Line 1,042 ⟶ 1,356:
 
string[] solution;
foreach (ref name; pokemon) {
swaptrySwap(pokemon[0], name, 0, solution);
search(pokemon, 1, solution);
swap(pokemon[0], name);
}
 
writefln("%-(%s\n%)", solution);
}</langsyntaxhighlight>
Output:
<pre>machamp
Line 1,074 ⟶ 1,385:
emolga
audino</pre>
The run-time is about 0.9 seconds with the dmd compiler and about 0.8155 seconds with the ldc2 compiler.
 
===Improved Version===
With two small changes the code gets faster. Here the names are represented as in C (so swapping them means just swapping a pointer, instead of swapping a pointer+length as before), and during the computation their last char is swapped with their second char (so there's no need to keep the string lengths around or use strlen).
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string, std.array, std.conv;
 
void search(immutable(char)*[] items, in int len,
Line 1,126 ⟶ 1,437:
 
writefln("%-(%s\n%)", solution.map!unprep);
}</langsyntaxhighlight>
 
This leads to tight enough code for the foreach loop in the search function:
 
<langsyntaxhighlight lang="asm">LBB0_4:
movl (%esi), %eax
movb 19(%esp), %cl
Line 1,153 ⟶ 1,464:
addl $4, %esi
decl %ebp
jne LBB0_4</langsyntaxhighlight>
 
The run-time is about 0.65 seconds with LDC2 compiler. The output is similar.
 
===Faster Version===
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.string, std.range, std.typecons;
 
Tuple!(uint, string[]) findLongestChain(in string[] words)
Line 1,239 ⟶ 1,550:
writeln("Example path of that length:");
writefln("%( %-(%s %)\n%)", sol[1].chunks(7));
}</langsyntaxhighlight>
{{out}}
<pre>Maximum path length: 23
Line 1,252 ⟶ 1,563:
===Alternative Version===
{{trans|PicoLisp}}
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.array, std.typecons,
std.container, std.range;
 
auto findChain(in string[] seq) /*pure nothrow /*@safe*/ {
const adj = seq
.map!(item => tuple(item, seq
seq .filter!(x => x[0] == item[$ - 1])
.filter!(x => x[0] == item[$-1] .array))
.array))
.assocArray;
SList!string res;
 
foreach (immutable item; adj.byKey) { // Not nothrow.
void inner(in string it, SList!string lst) nothrow {
lst.insertFront(it);
Line 1,277 ⟶ 1,587:
}
 
auto result =return res.array.retro;
return result.retro;
}
 
void main() /*@safe*/ {
"audino bagon baltoy banette bidoof braviary
bronzor carracosta charmeleon cresselia croagunk darmanitan deino
Line 1,292 ⟶ 1,601:
spoink starly tirtouga trapinch treecko tyrogue vigoroth vulpix
wailord wartortle whismur wingull yamask".split.findChain.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>["machamp", "petilil", "landorus", "scrafty", "yamask", "kricketune", "emboar", "registeel", "loudred", "darmanitan", "nosepass", "simisear", "relicanth", "heatmor", "rufflet", "trapinch", "haxorus", "seaking", "girafarig", "gabite", "exeggcute", "emolga", "audino"]</pre>
Line 1,299 ⟶ 1,608:
=={{header|Delphi}}==
Visual implementation, this unit is a VCL Form with a Memo, a Button, a Checkbox, a DataGrid, a DBMemo, a DataSource and a ClientDataSet with tree fields (length integer,count integer,list memo):
<langsyntaxhighlight lang="delphi">unit Unit1;
 
interface
Line 1,575 ⟶ 1,884:
end;
 
end.</langsyntaxhighlight>
Runtime varies depending if you run the "optimized" version or not. Ranges from 6 to 18 seconds.
 
NOTE: "optimized" version is actually a different algorithm, but in most cases returns the same results.
 
=={{header|EasyLang}}==
<syntaxhighlight>
repeat
s$ = input
until s$ = ""
for n$ in strsplit s$ " "
pok$[] &= n$
.
.
#
chain$[] = [ ]
proc search lng . .
if lng > len chain$[]
chain$[] = [ ]
for j to lng
chain$[] &= pok$[j]
.
.
lastc$ = substr pok$[lng] len pok$[lng] 1
for i = lng + 1 to len pok$[]
if substr pok$[i] 1 1 = lastc$
swap pok$[i] pok$[lng + 1]
search lng + 1
swap pok$[i] pok$[lng + 1]
.
.
.
for i to len pok$[]
swap pok$[i] pok$[1]
search 1
swap pok$[i] pok$[1]
.
for p$ in chain$[]
write p$ & " "
.
#
input_data
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
</syntaxhighlight>
{{out}}
<pre>
machamp petilil landorus scrafty yamask kricketune emboar registeel loudred darmanitan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite exeggcute emolga audino
</pre>
 
=={{header|Elixir}}==
{{trans|Ruby}}
<syntaxhighlight lang="elixir">defmodule LastLetter_FirstLetter do
def search(names) do
first = Enum.group_by(names, &String.first/1)
sequences = Enum.reduce(names, [], fn name,acc -> add_name(first, acc, [name]) end)
max = Enum.max_by(sequences, &length/1) |> length
max_seqs = Enum.filter(sequences, fn seq -> length(seq) == max end)
IO.puts "there are #{length(sequences)} possible sequences"
IO.puts "the longest is #{max} names long"
IO.puts "there are #{length(max_seqs)} such sequences. one is:"
hd(max_seqs) |> Enum.with_index |>
Enum.each(fn {name, idx} ->
:io.fwrite " ~2w ~s~n", [idx+1, name]
end)
end
defp add_name(first, sequences, seq) do
last_letter = String.last(hd(seq))
potentials = Map.get(first, last_letter, []) -- seq
if potentials == [] do
[Enum.reverse(seq) | sequences]
else
Enum.reduce(potentials, sequences, fn name, acc -> add_name(first, acc, [name | seq]) end)
end
end
end
 
names = ~w(
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
)
 
LastLetter_FirstLetter.search(names)</syntaxhighlight>
 
{{out}}
<pre>
there are 2076396 possible sequences
the longest is 23 names long
there are 1248 such sequences. one is:
1 machamp
2 petilil
3 landorus
4 scrafty
5 yamask
6 kricketune
7 emboar
8 registeel
9 loudred
10 darmanitan
11 nosepass
12 simisear
13 relicanth
14 heatmor
15 rufflet
16 trapinch
17 haxorus
18 seaking
19 girafarig
20 gabite
21 exeggcute
22 emolga
23 audino
</pre>
 
=={{header|Erlang}}==
This is a parallel version. It takes 2.1 seconds. The (commented out) serial version takes 7.1 seconds. Both times measured on my (low end) Mac Mini. I thought parallel code would help in getting the brownie points. But even a small increase to 100 Pokemons makes the code run for more than the few spare hours I have in the evening.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( last_letter_first_letter ).
 
Line 1,633 ⟶ 2,064:
 
names() -> <<"audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon cresselia croagunk darmanitan deino emboar emolga exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask">>.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,647 ⟶ 2,078:
=={{header|Go}}==
Depth first, starting with each possible name.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,702 ⟶ 2,133:
}
}
}</langsyntaxhighlight>
Output:
<pre>
Line 1,717 ⟶ 2,148:
=={{header|Haskell}}==
Note: This takes ~80 seconds to complete on my machine.
<langsyntaxhighlight Haskelllang="haskell">import Data.List
import qualified Data.ByteString.Char8 as B
 
Line 1,739 ⟶ 2,170:
isLink pl pr = B.last pl == B.head pr
 
main = mapM_ B.putStrLn $ growChains $ map (\x -> [x]) allPokemon</langsyntaxhighlight>
Output:
<pre>machamp
Line 1,765 ⟶ 2,196:
audino</pre>
A simpler version (no ByteString), about 2.4 times slower (GHC -O3), same output:
<langsyntaxhighlight Haskelllang="haskell">import Data.List
 
allPokemon = words
Line 1,785 ⟶ 2,216:
isLink pl pr = last pl == head pr
 
main = mapM_ putStrLn $ growChains $ map (\x -> [x]) allPokemon</langsyntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
Line 1,791 ⟶ 2,222:
Works in both languages (brute force):
 
<langsyntaxhighlight lang="unicon">global words
 
procedure main()
Line 1,814 ⟶ 2,245:
while l := !f do
l ? while tab(upto(&letters)) do suspend tab(many(&letters))\1
end</langsyntaxhighlight>
 
Sample run on sample data:
Line 1,827 ⟶ 2,258:
Here, we use a brute force breadth-first search. Unless we know ahead of time how long "longest" is, we must try all possibilities to ensure that an unchecked possibility is not longer than a possibility which we have found.
 
<langsyntaxhighlight lang="j">pokenames=: ;:0 :0-.LF
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
Line 1,847 ⟶ 2,278:
end.
r
)</langsyntaxhighlight>
 
The line <code>assert. 1e9>*/8,$r</code> was added to avoid a very bad behavior from microsoft windows which appeared on different arguments, when intermediate results became too large (the machine would have to be rebooted when intermediate results became an order of magnitude larger than the available physical memory). By ensuring that the program would end before consuming that much virtual memory, this behavior from the operating system can be avoided. Note that [http://www.jsoftware.com/help/dictionary/dx009.htm 9!:21 and/or 9!:33] could also be used to prevent OS instability triggered by requesting too many resources.
Line 1,853 ⟶ 2,284:
With this procedure we are able to conduct the entire search for this list of names:
 
<langsyntaxhighlight lang="j">$R=: seqs pokenames
1248 23</langsyntaxhighlight>
 
With this data set, we have 1248 sequences of names which have the longest possible length, and those sequences are 23 names long. Here's one of them:
 
<langsyntaxhighlight lang="j"> >pokenames {~{.R
machamp
petilil
Line 1,881 ⟶ 2,312:
exeggcute
emolga
audino </langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">// derived from C
final class LastLetterFirstLetter {
static int maxPathLength = 0;
Line 1,944 ⟶ 2,375:
}
}
</syntaxhighlight>
</lang>
 
Output:<pre>maximum path length : 23
Line 1,955 ⟶ 2,386:
gabite emolga audino
</pre>
 
=={{header|JavaScript}}==
{{Works with|Node.js}} (Required for the ''process'' object)
<syntaxhighlight lang="javascript">/**
* Find the letter the word ends on
* @param {string} word
* @returns {string}
*/
const endsWith = word => word[word.length - 1];
 
/**
* Remove the used elements from the candidate elements
* @param {Array<string>} words Candidate words
* @param {Array<string>} used Used words
* @returns {*}
*/
const getCandidates = (words, used) => words.filter(e => !used.includes(e));
 
/**
* Build a map of letters to words that start with that letter
* @param {Array<string>} words
* @returns {Map<string, Array<string>>}
*/
const buildLookup = words => {
const lookup = new Map();
words.forEach(e => {
const start = e[0];
lookup.set(start, [...(lookup.get(start) || []), e]);
});
return lookup;
};
 
 
/**
* Main function
* @param {Array<string>} names
*/
const findPaths = names => {
const t0 = process.hrtime();
console.log('Checking:', names.length, 'names');
const lookup = buildLookup(names);
 
let maxNum = 0;
let maxPaths = [];
 
const parseResult = arr => {
if (typeof arr[0] === 'object') {
arr.forEach(el => parseResult(el))
} else {
if (arr.length > maxNum) {
maxNum = arr.length;
maxPaths = [arr];
}
if (arr.length === maxNum) {
maxPaths.push(arr)
}
}
};
 
const searchWords = (word, res) => {
const cs = getCandidates(lookup.get(endsWith(word)) || [], res);
return cs.length ? cs.map(e => searchWords(e, [...res, e])) : res;
};
 
names.forEach(word => {
const res = searchWords(word, [word]);
parseResult(res);
});
 
const t1 = process.hrtime(t0);
console.info('Execution time (hr): %ds %dms', t1[0], t1[1] / 1000000);
console.log('Max Path:', maxNum);
console.log('Matching Paths:', maxPaths.length);
console.log('Example Path:', maxPaths[0]);
 
};
 
const pokimon = ["audino", "bagon", "baltoy", "banette",
"bidoof", "braviary", "bronzor", "carracosta", "charmeleon",
"cresselia", "croagunk", "darmanitan", "deino", "emboar",
"emolga", "exeggcute", "gabite", "girafarig", "gulpin",
"haxorus", "heatmor", "heatran", "ivysaur", "jellicent",
"jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba",
"loudred", "lumineon", "lunatone", "machamp", "magnezone",
"mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu",
"pinsir", "poliwrath", "poochyena", "porygon2", "porygonz",
"registeel", "relicanth", "remoraid", "rufflet", "sableye",
"scolipede", "scrafty", "seaking", "sealeo", "silcoon",
"simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga",
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix",
"wailord", "wartortle", "whismur", "wingull", "yamask"];
 
findPaths(pokimon);
</syntaxhighlight>
 
<pre>
Checking: 70 names
Execution time (hr): 2s 121.778223ms
Max Path: 23
Matching Paths: 1249
Example Path: [
'machamp',
'petilil',
'landorus',
'scrafty',
'yamask',
'kricketune',
'emboar',
'registeel',
'loudred',
'darmanitan',
'nosepass',
'simisear',
'relicanth',
'heatmor',
'rufflet',
'trapinch',
'haxorus',
'seaking',
'girafarig',
'gabite',
'exeggcute',
'emolga',
'audino' ]
</pre>
 
=={{header|jq}}==
Short and sweet, with a nod to efficiency in the form of a dictionary for lookup of still-available words.
 
jq's "debug" filter is used to illustrate how progress can be monitored.
It writes to stderr. If your jq does not include "debug", simply remove or comment-out the entire line.
 
'''Utility functions''':
<syntaxhighlight lang="jq"># convert a list of unique words to a dictionary
def dictionary:
reduce .[] as $word ({}; .[$word[0:1]] += [$word]) ;
 
# remove "word" from the input dictionary assuming the key is already there:
def remove(word):
.[word[0:1]] -= [word];</syntaxhighlight>
 
'''The last-letter/first-letter game''':
<syntaxhighlight lang="ja"># left-right admissibility
def admissible:
.[0][-1:] == .[1][0:1];
 
# input: [word, dictionary_of_available_words_excluding_word]
# output: a (possibly empty) stream of admissible values: [next_word, updated_dictionary],
# where next_word can follow the given word.
def next:
.[0] as $word
| if $word == null then empty
else .[1] as $dictionary
| $word[-1:] as $last
| (($dictionary[$last] // []) | .[]) as $next
| [ $next, ($dictionary | remove($next)) ]
end ;
 
# Produce an array representing a thread starting at "word":
# Input: [word, dictionary_of_available_words]
def thread:
if .[1] == [] then [ .[0] ]
else (next // null) as $next
| [.[0]] + (if $next then ($next | thread) else [] end)
end ;
 
# Input: list of words
# Output: [ maximal_length, maximal_thread]
def maximal:
def maximum(start):
. as $dictionary
| reduce ( [start, ($dictionary | remove(start))] | thread ) as $thread
([0, null];
($thread|length) as $l
| if $l > .[0] then [$l, $thread] else . end );
 
dictionary as $dictionary
| reduce .[] as $name
( [0,null];
($dictionary | maximum($name)) as $ans
# If your jq does not include "debug", simply remove or comment-out the following line:
| ([$name, $ans[0]] | debug) as $debug
| if $ans[0] > .[0] then $ans else . end );</syntaxhighlight>
'''Example''':
<syntaxhighlight lang="jq">def names:
["audino", "bagon", "baltoy", "banette",
"bidoof", "braviary", "bronzor", "carracosta", "charmeleon",
"cresselia", "croagunk", "darmanitan", "deino", "emboar",
"emolga", "exeggcute", "gabite", "girafarig", "gulpin",
"haxorus", "heatmor", "heatran", "ivysaur", "jellicent",
"jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba",
"loudred", "lumineon", "lunatone", "machamp", "magnezone",
"mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu",
"pinsir", "poliwrath", "poochyena", "porygon2", "porygonz",
"registeel", "relicanth", "remoraid", "rufflet", "sableye",
"scolipede", "scrafty", "seaking", "sealeo", "silcoon",
"simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga",
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix",
"wailord", "wartortle", "whismur", "wingull", "yamask" ] ;
 
names | maximal</syntaxhighlight>
 
{{out}} (scrollable)
The "DEBUG" lines are included to illustrate how progress can be monitored. They show the maximal length for the indicated initial word.
<div style="overflow:scroll; height:400px;">
<syntaxhighlight lang="sh">$ jq -n -f Last_letter-first_letter.jq
["DEBUG:",["audino",1]]
["DEBUG:",["bagon",20]]
["DEBUG:",["baltoy",21]]
["DEBUG:",["banette",20]]
["DEBUG:",["bidoof",1]]
["DEBUG:",["braviary",21]]
["DEBUG:",["bronzor",22]]
["DEBUG:",["carracosta",2]]
["DEBUG:",["charmeleon",20]]
["DEBUG:",["cresselia",2]]
["DEBUG:",["croagunk",21]]
["DEBUG:",["darmanitan",20]]
["DEBUG:",["deino",1]]
["DEBUG:",["emboar",19]]
["DEBUG:",["emolga",2]]
["DEBUG:",["exeggcute",19]]
["DEBUG:",["gabite",20]]
["DEBUG:",["girafarig",20]]
["DEBUG:",["gulpin",20]]
["DEBUG:",["haxorus",20]]
["DEBUG:",["heatmor",20]]
["DEBUG:",["heatran",20]]
["DEBUG:",["ivysaur",22]]
["DEBUG:",["jellicent",21]]
["DEBUG:",["jumpluff",1]]
["DEBUG:",["kangaskhan",20]]
["DEBUG:",["kricketune",20]]
["DEBUG:",["landorus",21]]
["DEBUG:",["ledyba",2]]
["DEBUG:",["loudred",21]]
["DEBUG:",["lumineon",20]]
["DEBUG:",["lunatone",20]]
["DEBUG:",["machamp",23]]
["DEBUG:",["magnezone",20]]
["DEBUG:",["mamoswine",20]]
["DEBUG:",["nosepass",19]]
["DEBUG:",["petilil",22]]
["DEBUG:",["pidgeotto",1]]
["DEBUG:",["pikachu",1]]
["DEBUG:",["pinsir",22]]
["DEBUG:",["poliwrath",21]]
["DEBUG:",["poochyena",2]]
["DEBUG:",["porygon2",1]]
["DEBUG:",["porygonz",1]]
["DEBUG:",["registeel",21]]
["DEBUG:",["relicanth",21]]
["DEBUG:",["remoraid",21]]
["DEBUG:",["rufflet",21]]
["DEBUG:",["sableye",20]]
["DEBUG:",["scolipede",20]]
["DEBUG:",["scrafty",21]]
["DEBUG:",["seaking",21]]
["DEBUG:",["sealeo",1]]
["DEBUG:",["silcoon",20]]
["DEBUG:",["simisear",21]]
["DEBUG:",["snivy",21]]
["DEBUG:",["snorlax",1]]
["DEBUG:",["spoink",21]]
["DEBUG:",["starly",21]]
["DEBUG:",["tirtouga",2]]
["DEBUG:",["trapinch",20]]
["DEBUG:",["treecko",1]]
["DEBUG:",["tyrogue",20]]
["DEBUG:",["vigoroth",21]]
["DEBUG:",["vulpix",1]]
["DEBUG:",["wailord",21]]
["DEBUG:",["wartortle",20]]
["DEBUG:",["whismur",22]]
["DEBUG:",["wingull",22]]
["DEBUG:",["yamask",20]]
[
23,
[
"machamp",
"petilil",
"landorus",
"scrafty",
"yamask",
"kricketune",
"emboar",
"registeel",
"loudred",
"darmanitan",
"nosepass",
"simisear",
"relicanth",
"heatmor",
"rufflet",
"trapinch",
"haxorus",
"seaking",
"girafarig",
"gabite",
"exeggcute",
"emolga",
"audino"
]
]</syntaxhighlight></div>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
{{trans|Python}}
 
<syntaxhighlight lang="julia">using IterTools.groupby
 
orderwords(words::Vector) = Dict(w[1][1] => Set(w) for w in groupby(first, words))
longest(a, b) = ifelse(length(a) > length(b), a, b)
function linkfirst(byfirst::Dict, sofar::Vector)
@assert(!isempty(sofar))
chmatch = sofar[end][end]
if ! haskey(byfirst, chmatch) return sofar end
options = setdiff(byfirst[chmatch], sofar)
if isempty(options)
return sofar
else
alternatives = ( linkfirst(byfirst, vcat(sofar, word)) for word in options )
mx = reduce(longest, alternatives)
return mx
end
end
function llfl(words)
byfirst = orderwords(words)
alternatives = ( linkfirst(byfirst, [word]) for word in words )
return reduce(longest, alternatives)
end
 
pokemon = String.(unique(split("""
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
""")))
 
l = llfl(pokemon)
println("Example of longest seq.:\n", join(l, ", "))
println("Max length: ", length(l)</syntaxhighlight>
 
{{out}}
<pre>Example of longest seq.:
machamp, pinsir, relicanth, heatmor, registeel, landorus, starly, yamask, kricketune, emboar, rufflet, trapinch, haxorus, simisear, remoraid, darmanitan, nosepass, seaking, girafarig, gabite, exeggcute, emolga, audino
Max length: 23</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">// version 1.1.2
 
var maxPathLength = 0
var maxPathLengthCount = 0
val maxPathExample = StringBuilder(500)
 
val names = arrayOf(
"audino", "bagon", "baltoy", "banette", "bidoof",
"braviary", "bronzor", "carracosta", "charmeleon", "cresselia",
"croagunk", "darmanitan", "deino", "emboar", "emolga",
"exeggcute", "gabite", "girafarig", "gulpin", "haxorus",
"heatmor", "heatran", "ivysaur", "jellicent", "jumpluff",
"kangaskhan", "kricketune", "landorus", "ledyba", "loudred",
"lumineon", "lunatone", "machamp", "magnezone", "mamoswine",
"nosepass", "petilil", "pidgeotto", "pikachu", "pinsir",
"poliwrath", "poochyena", "porygon2", "porygonz", "registeel",
"relicanth", "remoraid", "rufflet", "sableye", "scolipede",
"scrafty", "seaking", "sealeo", "silcoon", "simisear",
"snivy", "snorlax", "spoink", "starly", "tirtouga",
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix",
"wailord", "wartortle", "whismur", "wingull", "yamask"
)
 
fun search(part: Array<String>, offset: Int) {
if (offset > maxPathLength) {
maxPathLength = offset
maxPathLengthCount = 1
}
else if (offset == maxPathLength) {
maxPathLengthCount++
maxPathExample.setLength(0)
for (i in 0 until offset) {
maxPathExample.append(if (i % 5 == 0) "\n " else " ")
maxPathExample.append(part[i])
}
}
val lastChar = part[offset - 1].last()
for (i in offset until part.size) {
if (part[i][0] == lastChar) {
val tmp = names[offset]
names[offset] = names[i]
names[i] = tmp
search(names, offset + 1)
names[i] = names[offset]
names[offset] = tmp
}
}
}
 
fun main(args: Array<String>) {
for (i in 0 until names.size) {
val tmp = names[0]
names[0] = names[i]
names[i] = tmp
search(names, 1)
names[i] = names[0]
names[0] = tmp
}
println("Maximum path length : $maxPathLength")
println("Paths of that length : $maxPathLengthCount")
println("Example path of that length : $maxPathExample")
}</syntaxhighlight>
 
{{out}}
<pre>
Maximum path length : 23
Paths of that length : 1248
Example path of that length :
machamp pinsir rufflet trapinch heatmor
remoraid darmanitan nosepass starly yamask
kricketune exeggcute emboar relicanth haxorus
simisear registeel landorus seaking girafarig
gabite emolga audino
</pre>
=={{header|Lua}}==
In lieu of the poorly-specified extra-credit portion (e.g. are the two Nidoran's to be considered same or unique?), I chose to expand on the output portion of the core task.
<syntaxhighlight lang="lua">-- BUILDING:
pokemon = [[
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask]]
words, inits, succs = {}, {}, {}
for word in pokemon:gmatch("%S+") do
table.insert(words, word)
local ch = word:sub(1,1)
inits[ch] = inits[ch] or {}
table.insert(inits[ch], word)
end
for _,word in pairs(words) do
succs[word] = {}
local ch = word:sub(-1,-1)
if inits[ch] then
for _,succ in pairs(inits[ch]) do
if succ~=word then
table.insert(succs[word],succ)
end
end
end
end
 
-- SEARCHING:
function expand(list, used, answer)
local word = list[#list]
for _,succ in ipairs(succs[word]) do
if not used[succ] then
used[succ] = true
list[#list+1] = succ
if #list == answer.len then
local perm = table.concat(list," ")
answer.perms[perm] = perm
answer.num = answer.num + 1
elseif #list > answer.len then
answer.len = #list
local perm = table.concat(list," ")
answer.perms = {[perm] = perm}
answer.num = 1
end
expand(list, used, answer)
list[#list] = nil
used[succ] = nil
end
end
end
answers = {}
for _,word in ipairs(words) do
local answer = { word=word, len=0, num=0, perms={} }
answers[#answers+1] = answer
expand({word}, {[word]=true}, answer)
end
 
-- REPORTING:
table.sort(answers, function(a,b) return a.len<b.len or (a.len==b.len and a.word<b.word) end)
print("first word length count example")
print("---------- ------ ----- -------...")
for _,answer in pairs(answers) do
local perm = next(answer.perms) or ""
print(string.format("%10s %6d %5d %s", answer.word, answer.len, answer.num, perm))
end</syntaxhighlight>
{{out}}
<pre>first word length count example
---------- ------ ----- -------...
audino 0 0
bidoof 0 0
deino 0 0
jumpluff 0 0
pidgeotto 0 0
pikachu 0 0
porygon2 0 0
porygonz 0 0
sealeo 0 0
snorlax 0 0
treecko 0 0
vulpix 0 0
carracosta 2 1 carracosta audino
cresselia 2 1 cresselia audino
emolga 2 1 emolga audino
ledyba 2 1 ledyba audino
poochyena 2 1 poochyena audino
tirtouga 2 1 tirtouga audino
emboar 19 96 emboar relicanth heatmor rufflet trapinch haxorus simisear registeel landorus seaking girafarig gulpin nosepass scrafty yamask kricketune exeggcute emolga audino
exeggcute 19 96 exeggcute emboar relicanth haxorus seaking girafarig gulpin nosepass simisear rufflet trapinch heatmor registeel landorus snivy yamask kricketune emolga audino
nosepass 19 192 nosepass snivy yamask kricketune exeggcute emboar rufflet trapinch heatmor registeel landorus simisear relicanth haxorus seaking girafarig gabite emolga audino
bagon 20 192 bagon nosepass simisear relicanth heatmor rufflet trapinch haxorus scrafty yamask kricketune emboar registeel landorus seaking girafarig gabite exeggcute emolga audino
banette 20 192 banette exeggcute emboar relicanth heatmor registeel landorus starly yamask kangaskhan nosepass simisear rufflet trapinch haxorus seaking girafarig gabite emolga audino
charmeleon 20 192 charmeleon nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite emboar registeel landorus starly yamask kricketune exeggcute emolga audino
darmanitan 20 192 darmanitan nosepass seaking girafarig gabite exeggcute emboar relicanth haxorus simisear rufflet trapinch heatmor registeel landorus starly yamask kricketune emolga audino
gabite 20 96 gabite emboar rufflet trapinch heatmor relicanth haxorus simisear registeel landorus seaking girafarig gulpin nosepass snivy yamask kricketune exeggcute emolga audino
girafarig 20 480 girafarig gabite emboar registeel landorus spoink kangaskhan nosepass simisear rufflet trapinch heatmor relicanth haxorus snivy yamask kricketune exeggcute emolga audino
gulpin 20 192 gulpin nosepass simisear rufflet trapinch heatmor relicanth haxorus snivy yamask kricketune emboar registeel landorus seaking girafarig gabite exeggcute emolga audino
haxorus 20 288 haxorus starly yamask kricketune exeggcute emboar registeel landorus simisear rufflet trapinch heatmor remoraid darmanitan nosepass seaking girafarig gabite emolga audino
heatmor 20 432 heatmor rufflet trapinch heatran nosepass simisear relicanth haxorus seaking girafarig gabite emboar registeel landorus starly yamask kricketune exeggcute emolga audino
heatran 20 192 heatran nosepass simisear relicanth haxorus seaking girafarig gabite exeggcute emboar rufflet trapinch heatmor registeel landorus starly yamask kricketune emolga audino
kangaskhan 20 192 kangaskhan nosepass seaking girafarig gabite exeggcute emboar relicanth haxorus simisear rufflet trapinch heatmor registeel landorus starly yamask kricketune emolga audino
kricketune 20 96 kricketune exeggcute emboar relicanth heatmor rufflet trapinch haxorus simisear registeel landorus scrafty yamask kangaskhan nosepass seaking girafarig gabite emolga audino
lumineon 20 192 lumineon nosepass seaking girafarig gabite exeggcute emboar rufflet trapinch heatmor relicanth haxorus simisear registeel landorus starly yamask kricketune emolga audino
lunatone 20 192 lunatone emboar rufflet trapinch heatmor registeel landorus starly yamask kangaskhan nosepass simisear relicanth haxorus seaking girafarig gabite exeggcute emolga audino
magnezone 20 192 magnezone exeggcute emboar registeel landorus snivy yamask kangaskhan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite emolga audino
mamoswine 20 192 mamoswine exeggcute emboar relicanth haxorus seaking girafarig gulpin nosepass simisear rufflet trapinch heatmor registeel landorus snivy yamask kricketune emolga audino
sableye 20 192 sableye emboar relicanth heatmor registeel landorus simisear rufflet trapinch haxorus seaking girafarig gulpin nosepass starly yamask kricketune exeggcute emolga audino
scolipede 20 192 scolipede exeggcute emboar relicanth haxorus seaking girafarig gulpin nosepass simisear rufflet trapinch heatmor registeel landorus snivy yamask kricketune emolga audino
silcoon 20 192 silcoon nosepass simisear rufflet trapinch haxorus scrafty yamask kricketune exeggcute emboar relicanth heatmor registeel landorus seaking girafarig gabite emolga audino
trapinch 20 576 trapinch heatmor registeel landorus simisear remoraid darmanitan nosepass scrafty yamask kricketune exeggcute emboar relicanth haxorus seaking girafarig gabite emolga audino
tyrogue 20 192 tyrogue emboar rufflet trapinch heatmor registeel landorus seaking girafarig gulpin nosepass simisear relicanth haxorus snivy yamask kricketune exeggcute emolga audino
wartortle 20 192 wartortle exeggcute emboar registeel landorus snivy yamask kangaskhan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite emolga audino
yamask 20 96 yamask kangaskhan nosepass seaking girafarig gabite emboar rufflet trapinch heatmor registeel landorus simisear relicanth haxorus spoink kricketune exeggcute emolga audino
baltoy 21 96 baltoy yamask kangaskhan nosepass simisear rufflet trapinch heatmor relicanth haxorus seaking girafarig gabite exeggcute emboar registeel landorus spoink kricketune emolga audino
braviary 21 96 braviary yamask kangaskhan nosepass seaking girafarig gabite exeggcute emboar relicanth haxorus simisear rufflet trapinch heatmor registeel landorus spoink kricketune emolga audino
croagunk 21 288 croagunk kangaskhan nosepass seaking girafarig gabite emboar rufflet trapinch heatmor registeel landorus simisear relicanth haxorus starly yamask kricketune exeggcute emolga audino
jellicent 21 768 jellicent trapinch haxorus seaking girafarig gabite exeggcute emboar relicanth heatmor remoraid darmanitan nosepass simisear registeel landorus snivy yamask kricketune emolga audino
landorus 21 192 landorus seaking girafarig gabite emboar relicanth heatmor rufflet trapinch haxorus simisear registeel loudred darmanitan nosepass starly yamask kricketune exeggcute emolga audino
loudred 21 192 loudred darmanitan nosepass seaking girafarig gabite exeggcute emboar rufflet trapinch haxorus simisear relicanth heatmor registeel landorus snivy yamask kricketune emolga audino
poliwrath 21 912 poliwrath heatmor remoraid darmanitan nosepass simisear registeel landorus seaking girafarig gabite exeggcute emboar rufflet trapinch haxorus scrafty yamask kricketune emolga audino
registeel 21 192 registeel landorus simisear rufflet trapinch heatmor remoraid darmanitan nosepass seaking girafarig gabite exeggcute emboar relicanth haxorus starly yamask kricketune emolga audino
relicanth 21 240 relicanth heatmor rufflet trapinch haxorus simisear registeel landorus seaking girafarig gabite exeggcute emboar remoraid darmanitan nosepass starly yamask kricketune emolga audino
remoraid 21 192 remoraid darmanitan nosepass simisear relicanth heatmor registeel landorus scrafty yamask kricketune exeggcute emboar rufflet trapinch haxorus seaking girafarig gabite emolga audino
rufflet 21 240 rufflet trapinch heatmor remoraid darmanitan nosepass seaking girafarig gabite emboar registeel landorus simisear relicanth haxorus starly yamask kricketune exeggcute emolga audino
scrafty 21 96 scrafty yamask kricketune exeggcute emboar rufflet trapinch heatmor relicanth haxorus spoink kangaskhan nosepass simisear registeel landorus seaking girafarig gabite emolga audino
seaking 21 192 seaking girafarig gabite emboar rufflet trapinch heatmor relicanth haxorus simisear registeel landorus snivy yamask kangaskhan nosepass spoink kricketune exeggcute emolga audino
simisear 21 384 simisear rufflet trapinch haxorus spoink kricketune exeggcute emboar relicanth heatmor registeel landorus snivy yamask kangaskhan nosepass seaking girafarig gabite emolga audino
snivy 21 96 snivy yamask kricketune exeggcute emboar registeel landorus simisear rufflet trapinch heatmor relicanth haxorus spoink kangaskhan nosepass seaking girafarig gabite emolga audino
spoink 21 288 spoink kangaskhan nosepass snivy yamask kricketune emboar relicanth heatmor rufflet trapinch haxorus simisear registeel landorus seaking girafarig gabite exeggcute emolga audino
starly 21 96 starly yamask kangaskhan nosepass simisear rufflet trapinch heatmor relicanth haxorus seaking girafarig gabite exeggcute emboar registeel landorus spoink kricketune emolga audino
vigoroth 21 912 vigoroth haxorus simisear registeel landorus starly yamask kricketune exeggcute emboar rufflet trapinch heatmor remoraid darmanitan nosepass seaking girafarig gabite emolga audino
wailord 21 192 wailord darmanitan nosepass seaking girafarig gabite exeggcute emboar rufflet trapinch haxorus simisear relicanth heatmor registeel landorus snivy yamask kricketune emolga audino
bronzor 22 864 bronzor registeel landorus seaking girafarig gabite emboar rufflet trapinch heatmor remoraid darmanitan nosepass simisear relicanth haxorus snivy yamask kricketune exeggcute emolga audino
ivysaur 22 864 ivysaur registeel landorus seaking girafarig gabite emboar rufflet trapinch heatmor remoraid darmanitan nosepass simisear relicanth haxorus snivy yamask kricketune exeggcute emolga audino
petilil 22 384 petilil landorus simisear rufflet trapinch heatmor relicanth haxorus starly yamask kricketune exeggcute emboar registeel loudred darmanitan nosepass seaking girafarig gabite emolga audino
pinsir 22 864 pinsir rufflet trapinch heatmor registeel landorus seaking girafarig gabite exeggcute emboar relicanth haxorus simisear remoraid darmanitan nosepass snivy yamask kricketune emolga audino
whismur 22 864 whismur registeel landorus seaking girafarig gabite emboar rufflet trapinch heatmor remoraid darmanitan nosepass simisear relicanth haxorus snivy yamask kricketune exeggcute emolga audino
wingull 22 384 wingull landorus snivy yamask kricketune emboar rufflet trapinch haxorus simisear relicanth heatmor registeel loudred darmanitan nosepass seaking girafarig gabite exeggcute emolga audino
machamp 23 1248 machamp petilil landorus simisear relicanth haxorus starly yamask kricketune exeggcute emboar rufflet trapinch heatmor registeel loudred darmanitan nosepass seaking girafarig gabite emolga audino</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">longestChain[list_] :=
NestWhileList[
Append @@@
Select[DeleteDuplicatesBy[
Tuples[{#, list}], {#[[1, 1]], #[[2]]} &], ! MemberQ @@ # &&
StringTake[#[[1, -1]], -1] == StringTake[#[[2]], 1] &] &,
List /@ list, # != {} &][[-2, 1]];
Print[longestChain[{"audino", "bagon", "baltoy", "banette", "bidoof",
"braviary", "bronzor", "carracosta", "charmeleon", "cresselia",
"croagunk", "darmanitan", "deino", "emboar", "emolga",
"exeggcute", "gabite", "girafarig", "gulpin", "haxorus",
"heatmor", "heatran", "ivysaur", "jellicent", "jumpluff",
"kangaskhan", "kricketune", "landorus", "ledyba", "loudred",
"lumineon", "lunatone", "machamp", "magnezone", "mamoswine",
"nosepass", "petilil", "pidgeotto", "pikachu", "pinsir",
"poliwrath", "poochyena", "porygon2", "porygonz", "registeel",
"relicanth", "remoraid", "rufflet", "sableye", "scolipede",
"scrafty", "seaking", "sealeo", "silcoon", "simisear", "snivy",
"snorlax", "spoink", "starly", "tirtouga", "trapinch", "treecko",
"tyrogue", "vigoroth", "vulpix", "wailord", "wartortle",
"whismur", "wingull", "yamask"}]];</syntaxhighlight>
Uses the tactic of only checking chains with the same starting and ending values.
{{out}}
<pre>{baltoy, yamask, kangaskhan, nosepass, sableye, emboar, registeel, landorus, scolipede, emolga, audino}</pre>
 
=={{header|Nim}}==
Using bit sets of indexes. The program runs in 0.5s.
<syntaxhighlight lang="nim">import tables
 
const Names = ["audino", "bagon", "baltoy", "banette", "bidoof", "braviary", "bronzor",
"carracosta", "charmeleon", "cresselia", "croagunk", "darmanitan", "deino",
"emboar", "emolga", "exeggcute", "gabite", "girafarig", "gulpin", "haxorus",
"heatmor", "heatran", "ivysaur", "jellicent", "jumpluff", "kangaskhan",
"kricketune", "landorus", "ledyba", "loudred", "lumineon", "lunatone",
"machamp", "magnezone", "mamoswine", "nosepass", "petilil", "pidgeotto",
"pikachu", "pinsir", "poliwrath", "poochyena", "porygon2", "porygonz",
"registeel", "relicanth", "remoraid", "rufflet", "sableye", "scolipede",
"scrafty", "seaking", "sealeo", "silcoon", "simisear", "snivy", "snorlax",
"spoink", "starly", "tirtouga", "trapinch", "treecko", "tyrogue", "vigoroth",
"vulpix", "wailord", "wartortle", "whismur", "wingull", "yamask"]
 
type
Index = range[0..Names.len-1]
IndexSet = set[Index]
Successors = Table[Index, IndexSet]
 
const All = {Index.low..Index.high} # All indexes.
 
 
func initSuccessors(): Successors {.compileTime.} =
## Build the mapping from name indexes to set of possible successor indexes.
 
var names: Table[char, IndexSet] # Map first char to IndexSet.
for idx, name in Names:
names.mgetOrPut(name[0], {}).incl(idx)
for idx, name in Names:
result[idx] = names.getOrDefault(name[^1]) - {idx}
 
# Mapping name index -> set of successor indexes.
const Succ = initSuccessors()
 
 
proc search(starts, available: IndexSet): seq[Index] =
## Search one of the longest sequence of indexes for given
## starting indexes and given available name indexes.
var maxLen = -1
for idx in starts * available:
let list = search(Succ[idx], available - {idx})
if list.len > maxLen:
result = idx & list
maxLen = list.len
 
 
let list = search(starts = All, available = All)
echo "Longest lists have length: ", list.len
echo "One of these lists is:"
for idx in list: echo Names[idx]</syntaxhighlight>
 
{{out}}
<pre>Longest lists have length: 23
One of these lists is:
machamp
petilil
landorus
scrafty
yamask
kricketune
emboar
registeel
loudred
darmanitan
nosepass
simisear
relicanth
heatmor
rufflet
trapinch
haxorus
seaking
girafarig
gabite
exeggcute
emolga
audino</pre>
 
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
<lang ooRexx>
-- create the searcher and run it
searcher = .chainsearcher~new
Line 2,032 ⟶ 3,139:
end
end
</syntaxhighlight>
</lang>
<pre>
searching 70 names...
Line 2,066 ⟶ 3,173:
The following gets the job done, but the time taken (40 minutes) is somewhat worrying when compared to other language solutions. So I am not going after the brownie points just yet...
 
<langsyntaxhighlight lang="progress">DEFINE VARIABLE cpokemon AS CHARACTER INITIAL "audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon ~
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite ~
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan ~
Line 2,149 ⟶ 3,256:
IF lcontinue = FALSE THEN
STOP.
END.</langsyntaxhighlight>
 
Output:
Line 2,165 ⟶ 3,272:
Yes No
---------------------------</pre>
 
=={{header|PicoLisp}}==
<lang PicoLisp>(de pokemonChain (File)
(let Names (make (in File (while (read) (link @))))
(for Name Names
(let C (last (chop Name))
(set Name
(filter '((Nm) (pre? C Nm)) Names) ) ) )
(let Res NIL
(for Name Names
(let Lst NIL
(recur (Name Lst)
(if (or (memq Name Lst) (not (val (push 'Lst Name))))
(when (> (length Lst) (length Res))
(setq Res Lst) )
(mapc recurse (val Name) (circ Lst)) ) ) ) )
(flip Res) ) ) )</lang>
Test:
<pre>
: (pokemonChain "pokemon.list")
-> (machamp petilil landorus scrafty yamask kricketune emboar registeel loudred
darmanitan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking
girafarig gabite exeggcute emolga audino)
: (length @)
-> 23
</pre>
 
=={{header|Perl}}==
Line 2,201 ⟶ 3,282:
*@m keeps the longest sequence which is copied from @w;
*to prevent the words from appearing twice, they are (temporarily) deleted from the structure keeping the value in a stack variable.
<syntaxhighlight lang="perl">use strict;
my(%f,@m);
 
<lang perl>/^(.).*(.)$/,$f{$1}{$_}=$2 for qw(
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
Line 2,213 ⟶ 3,296:
);
 
sub poke {
our @w;
{
my $h = $f{$_[0]};
for my $wword (keys %$h) {
my $v = $h->{$wword};
delete $h->{$wword};
push @w, $wword;
@m = @w if @w > @m;
poke($v);
pop @w;
$h->{$wword} = $v;
}
}
}
 
poke($_) for keys %f;
print @m.": @m\n";</langsyntaxhighlight>
{{out}}
Output:
<pre>23: machamp petilil landorus seaking girafarig gabite emboar registeel loudred darmanitan nosepass simisear relicanth heatmor rufflet trapinch haxorus scrafty yamask kricketune exeggcute emolga audino</pre>
=={{header|Perl 6}}==
A breadth-first search that uses disk files to avoid memory exhaustion. Each candidate sequence is encoded at one character per name, so to avoid reuse of names we merely have to make sure there are no repeat characters in our encoded string. (The encoding starts at ASCII space for the first name, so newline is not among the encoded characters.)
<lang perl6>my @names = <
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
>;
 
=={{header|Phix}}==
my @last = @names.map: {.substr(*-1,1).ord }
Using simple start-with-same-letter word chains to minimise the number of elements we have to consider:
my @succs = [] xx 128;
<!--<syntaxhighlight lang="phix">(phixonline)-->
for @names.kv -> $i, $name {
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
my $ix = $name.ord; # $name.substr(0,1).ord
<span style="color: #008080;">constant</span> <span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"audino"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"bagon"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"baltoy"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"banette"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"bidoof"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"braviary"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"bronzor"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"carracosta"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"charmeleon"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cresselia"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"croagunk"</span><span style="color: #0000FF;">,</span>
push @succs[$ix], $i;
<span style="color: #008000;">"darmanitan"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"deino"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"emboar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"emolga"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"exeggcute"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gabite"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"girafarig"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gulpin"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"haxorus"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"heatmor"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"heatran"</span><span style="color: #0000FF;">,</span>
}
<span style="color: #008000;">"ivysaur"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"jellicent"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"jumpluff"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"kangaskhan"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"kricketune"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"landorus"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ledyba"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"loudred"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lumineon"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lunatone"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"machamp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"magnezone"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mamoswine"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nosepass"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"petilil"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pidgeotto"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pikachu"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pinsir"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"poliwrath"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"poochyena"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"porygon2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"porygonz"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"registeel"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"relicanth"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"remoraid"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rufflet"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"sableye"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"scolipede"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"scrafty"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"seaking"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"sealeo"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"silcoon"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"simisear"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"snivy"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"snorlax"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"spoink"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"starly"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tirtouga"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"trapinch"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"treecko"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tyrogue"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"vigoroth"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"vulpix"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wailord"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wartortle"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"whismur"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wingull"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"yamask"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">word_chains</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- start of chains for a given letter
-- first['a']=1, first['b']=2, first['c']=8, etc.</span>
<span style="color: #000000;">snext</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- chains of words starting with the same letter
-- a: snext[1]=0, b: snext[2..7]={3,4,5,6,7,0}, etc.</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;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</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;">first</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">first</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</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;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">ch</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">snext</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: #000000;">j</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;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">first</span><span style="color: #0000FF;">,</span><span style="color: #000000;">snext</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">first</span><span style="color: #0000FF;">,</span><span style="color: #000000;">snext</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word_chains</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">-- maintain words already taken as a linked list:</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">tstart</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">taken</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- 0=no, -1=end of chain, +ve=next
-- and keep a copy of the best for later</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bstart</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">best</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">maxn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">count</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">find_path</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">last</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">next</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">first</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">next</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">taken</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">taken</span><span style="color: #0000FF;">[</span><span style="color: #000000;">last</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next</span>
<span style="color: #000000;">taken</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #000000;">find_path</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">][$],</span><span style="color: #000000;">next</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">taken</span><span style="color: #0000FF;">[</span><span style="color: #000000;">last</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #000000;">taken</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">next</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">snext</span><span style="color: #0000FF;">[</span><span style="color: #000000;">next</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">></span><span style="color: #000000;">maxn</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">bstart</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tstart</span>
<span style="color: #000000;">best</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">taken</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">maxn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">maxn</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">time</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;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">tstart</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #000000;">taken</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: #000000;">1</span>
<span style="color: #000000;">find_path</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</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: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">taken</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: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</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;">"Runtime: %2.3f seconds. Max length:%d, found %d of such, one of which is:\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">maxn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">count</span><span style="color: #0000FF;">})</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">bstart</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">bstart</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">bstart</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">best</span><span style="color: #0000FF;">[</span><span style="color: #000000;">bstart</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">maxn</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;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join_by</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: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Runtime: 0.625 seconds. Max length:23, found 1248 of such, one of which is:
machamp petilil landorus scrafty yamask kricketune emboar registeel loudred darmanitan
nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking girafarig gabite
exeggcute emolga audino
</pre>
My claim for the extra brownie points, using the list from the Racket entry:
<pre>
Runtime: 0.000 seconds. Max length:2, found 9 of such, one of which is:
Porygon-Z Zubat
</pre>
Which is quite correct: 9 names begin with 'Z', and plenty with 'T' but none with 't' ;-)<br>
Adding a couple of upper(), it found a 302 in a couple of minutes but was still on permutations starting
with word[1] when I got bored and killed it, quickly calculating at the very least another 4.5 days and
quite probably not finishing within my lifetime...
 
=={{header|Picat}}==
my $OUT = open "llfl.new", :w or die "Can't create llfl.new: $!";
It's a little faster with the words sorted on decreasing lengths (<code>words2</code>): 9.43s vs 11.742s.
$OUT.print: chr($_ + 32),"\n" for 0 ..^ @names;
<syntaxhighlight lang="picat">go =>
close $OUT;
words(Words),
my $new = +@names;
my $len = 1;
% Words that starts with same letter as <this words>'s last letter.
Starts = new_map(),
foreach(Word in Words)
S = [ Word2 : Word2 in Words, Word != Word2, Word.last() = Word2.first()],
Starts.put(Word,S)
end,
% Sort the words according to lengths in decreasing order.
Words2 = [W : W=_ in Starts.map_to_list().qsort(sort_len)],
 
% Start the search
while $new {
MaxLen = _,
say "Length { $len++ }: $new candidates";
Continue := true,
shell 'mv llfl.new llfl.known';
foreach(Len in 2..Words.len, break(Continue == false))
my $IN = open "llfl.known" or die "Can't reopen llfl.known: $!";
if play1(Words2,Starts,Len,_List) then
my $OUT = open "llfl.new", :w or die "Can't create llfl.new: $!";
$new MaxLen := 0;Len
else
Continue := false
end
end,
println(maxLen=MaxLen),
% And present the result.
println("\nGet some (5) solutions:"),
get_some_solutions(Words2, Starts, MaxLen,5),
 
println("\nNnumber of optimal solutions:"),
NumSols = count_all(play1(Words2,Starts,MaxLen,_List)),
println(num_sols=NumSols),
nl.
 
 
% Check if it's possible to create a list of length Len.
play1(Words, Starts, Len, LLFL) :-
LLFL1 = new_list(Len),
select(LLFL1[1], Words, Rest),
C = 2,
while (C <= Len)
Among = Starts.get(LLFL1[C-1]),
Among != [],
select(Word,Among,Rest2),
not membchk(Word,LLFL1[1..C-1]),
LLFL1[C] := Word,
Rest := Rest2,
C := C + 1
end,
LLFL = LLFL1.
 
 
% Print NumSols solutions
get_some_solutions(Words,Starts,FoundLen,NumSols) =>
Map = get_global_map(),
Map.put(count,1),
play1(Words, Starts, FoundLen, LLFL),
println(LLFL),
C = Map.get(count),
if C < NumSols then Map.put(count,C+1), fail end.
 
 
% qsort(List, SortFunction)
% returns a sorted list according to the sort function SortFunction.
qsort([],_F) = [].
qsort([H|T],F) = qsort([E : E in T, call(F,E,H)], F)
++ [H] ++
qsort([E : E in T, not call(F,E,H)],F).
 
% Sort according to length
sort_len((_K1=V1),(_K2=V2)) :-
V1.len >= V2.len.
 
words(Words) =>
Words =
[
"audino", "bagon", "baltoy", "banette", "bidoof", "braviary", "bronzor", "carracosta", "charmeleon",
"cresselia", "croagunk", "darmanitan", "deino", "emboar", "emolga", "exeggcute", "gabite",
"girafarig", "gulpin", "haxorus", "heatmor", "heatran", "ivysaur", "jellicent", "jumpluff", "kangaskhan",
"kricketune", "landorus", "ledyba", "loudred", "lumineon", "lunatone", "machamp", "magnezone", "mamoswine",
"nosepass", "petilil", "pidgeotto", "pikachu", "pinsir", "poliwrath", "poochyena", "porygon2",
"porygonz", "registeel", "relicanth", "remoraid", "rufflet", "sableye", "scolipede", "scrafty", "seaking",
"sealeo", "silcoon", "simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga", "trapinch", "treecko",
"tyrogue", "vigoroth", "vulpix", "wailord", "wartortle", "whismur", "wingull", "yamask"
].</syntaxhighlight>
 
loop {
my $cand = $IN.get // last;
for @succs[@last[$cand.ord - 32]][] -> $i {
my $ic = chr($i + 32);
next if $cand ~~ /$ic/;
$OUT.print: $ic,$cand,"\n";
$new++;
}
}
$IN.close;
$OUT.close;
}
 
my $IN = open "llfl.known" or die "Can't reopen llfl.known: $!";
my $eg = $IN.lines.pick;
say "Length of longest: ", $eg.chars;
say join ' ', $eg.ords.reverse.map: { @names[$_ - 32] }</lang>
{{out}}
<pre>LengthmaxLen 1:= 70 candidates23
 
Length 2: 172 candidates
Get some (5) solutions:
Length 3: 494 candidates
[machamp,petilil,landorus,scrafty,yamask,kricketune,emboar,registeel,loudred,darmanitan,nosepass,simisear,relicanth,heatmor,rufflet,trapinch,haxorus,seaking,girafarig,gabite,exeggcute,emolga,audino]
Length 4: 1288 candidates
[machamp,petilil,landorus,scrafty,yamask,kricketune,emboar,registeel,loudred,darmanitan,nosepass,simisear,rufflet,trapinch,heatmor,relicanth,haxorus,seaking,girafarig,gabite,exeggcute,emolga,audino]
Length 5: 3235 candidates
[machamp,petilil,landorus,scrafty,yamask,kricketune,emboar,relicanth,haxorus,simisear,rufflet,trapinch,heatmor,registeel,loudred,darmanitan,nosepass,seaking,girafarig,gabite,exeggcute,emolga,audino]
Length 6: 7731 candidates
[machamp,petilil,landorus,scrafty,yamask,kricketune,emboar,relicanth,heatmor,registeel,loudred,darmanitan,nosepass,simisear,rufflet,trapinch,haxorus,seaking,girafarig,gabite,exeggcute,emolga,audino]
Length 7: 17628 candidates
[machamp,petilil,landorus,scrafty,yamask,kricketune,emboar,relicanth,heatmor,rufflet,trapinch,haxorus,simisear,registeel,loudred,darmanitan,nosepass,seaking,girafarig,gabite,exeggcute,emolga,audino]
Length 8: 37629 candidates
 
Length 9: 75122 candidates
Nnumber of optimal solutions:
Length 10: 139091 candidates
num_sols = 1248</pre>
Length 11: 236679 candidates
 
Length 12: 367405 candidates
=={{header|PicoLisp}}==
Length 13: 516210 candidates
<syntaxhighlight lang="picolisp">(de pokemonChain (File)
Length 14: 650916 candidates
(let Names (make (in File (while (read) (link @))))
Length 15: 733915 candidates
(for Name Names
Length 16: 727566 candidates
(let C (last (chop Name))
Length 17: 621835 candidates
(set Name
Length 18: 446666 candidates
(filter '((Nm) (pre? C Nm)) Names) ) ) )
Length 19: 260862 candidates
(let Res NIL
Length 20: 119908 candidates
(for Name Names
Length 21: 40296 candidates
(let Lst NIL
Length 22: 10112 candidates
(recur (Name Lst)
Length 23: 1248 candidates
(if (or (memq Name Lst) (not (val (push 'Lst Name))))
Length of longest: 23
(when (> (length Lst) (length Res))
machamp petilil loudred darmanitan nosepass simisear rufflet trapinch heatmor registeel landorus starly yamask kricketune exeggcute emboar relicanth haxorus seaking girafarig gabite emolga audino</pre>
(setq Res Lst) )
(mapc recurse (val Name) (circ Lst)) ) ) ) )
(flip Res) ) ) )</syntaxhighlight>
Test:
<pre>
: (pokemonChain "pokemon.list")
-> (machamp petilil landorus scrafty yamask kricketune emboar registeel loudred
darmanitan nosepass simisear relicanth heatmor rufflet trapinch haxorus seaking
girafarig gabite exeggcute emolga audino)
: (length @)
-> 23
</pre>
 
=={{header|Prolog}}==
Works with SWI-Prolog and module '''lambda.pl''' written by '''Ulrich Neumerkel''' found there http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl
<langsyntaxhighlight Prologlang="prolog">:- use_module(library(lambda)).
 
:- dynamic res/3.
Line 2,386 ⟶ 3,621:
atom_chars(A, LC),
reverse(LC, [L | _]).
</syntaxhighlight>
</lang>
Output :
<pre>?- time(last_first(Len, Nb, L)).
Line 2,396 ⟶ 3,631:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">from collections import defaultdict
 
def order_words(words):
Line 2,442 ⟶ 3,677:
l = llfl(pokemon)
for i in range(0, len(l), 8): print(' '.join(l[i:i+8]))
print(len(l))</langsyntaxhighlight>
 
;Sample output
<pre>machamp pinsir relicanth heatmor remoraid darmanitan nosepass snivy
<pre>audino bagon baltoy banette bidoof braviary bronzor carracosta
yamask kricketune exeggcute emboar registeel landorus simisear rufflet
charmeleon cresselia croagunk darmanitan deino emboar emolga exeggcute
trapinch haxorus seaking girafarig gabite emolga audino
gabite girafarig gulpin haxorus heatmor heatran ivysaur jellicent
23</pre>
===Alternative version===
Adapted from the D version. This uses Psyco.
<langsyntaxhighlight lang="python">import psyco
 
nsolutions = 0
Line 2,525 ⟶ 3,760:
 
psyco.full()
main()</langsyntaxhighlight>
Output:
<pre>Maximum path length: 23
Line 2,538 ⟶ 3,773:
=={{header|Racket}}==
This is a naive solution, which works fast enough as is (takes about 5 seconds on an old machine):
<langsyntaxhighlight lang="racket">#lang racket
 
(define names "
Line 2,568 ⟶ 3,803:
(printf "Longest chain found has ~a words:\n ~a\n"
(length longest) (string-join (map word-string longest) " -> "))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,578 ⟶ 3,813:
chains using three different combination/relinking functions. Not that the
definiton of `word` is slightly different here.
<langsyntaxhighlight lang="racket">#lang racket
(require "pokemon-names.rkt")
 
Line 2,760 ⟶ 3,995:
 
(time (longest-chain/constructive names-70 #:known-max 23))
(longest-chain/constructive names-646)</langsyntaxhighlight>
 
Run with ''racket -t last_letter-first_letter-randomised.rkt 2>&1'', to redirect standard error to
Line 2,820 ⟶ 4,055:
Karrablast Throh Happiny Yanmega Armaldo) 333)</pre>
'''File: pokemon-names.rkt'''
<langsyntaxhighlight lang="racket">#lang racket
(provide names-646 names-70)
(define names-70
Line 2,880 ⟶ 4,115:
Beartic Cryogonal Shelmet Accelgor Stunfisk Mienfoo Mienshao Druddigon Golett Golurk Pawniard Bisharp Bouffalant
Rufflet Braviary Vullaby Mandibuzz Heatmor Durant Deino Zweilous Hydreigon Larvesta Volcarona Cobalion Terrakion
Virizion Tornadus Thundurus Reshiram Zekrom Landorus Kyurem))</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
A breadth-first search that uses disk files to avoid memory exhaustion. Each candidate sequence is encoded at one character per name, so to avoid reuse of names we merely have to make sure there are no repeat characters in our encoded string. (The encoding starts at ASCII space for the first name, so newline is not among the encoded characters.)
<syntaxhighlight lang="raku" line>my @names = <
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
>;
 
my @last = @names.map: {.substr(*-1,1).ord }
my @succs = [] xx 128;
for @names.kv -> $i, $name {
my $ix = $name.ord; # $name.substr(0,1).ord
push @succs[$ix], $i;
}
 
my $OUT = open "llfl.new", :w orelse .die;
$OUT.print: chr($_ + 32),"\n" for 0 ..^ @names;
close $OUT;
my $new = +@names;
my $len = 1;
 
while $new {
say "Length { $len++ }: $new candidates";
shell 'mv llfl.new llfl.known';
my $IN = open "llfl.known" orelse .die;
my $OUT = open "llfl.new", :w orelse .die;
$new = 0;
 
loop {
my $cand = $IN.get // last;
for @succs[@last[$cand.ord - 32]][] -> $i {
my $ic = chr($i + 32);
next if $cand ~~ /$ic/;
$OUT.print: $ic,$cand,"\n";
$new++;
}
}
$IN.close;
$OUT.close;
}
 
my $IN = open "llfl.known" orelse .die;
my $eg = $IN.lines.pick;
say "Length of longest: ", $eg.chars;
say join ' ', $eg.ords.reverse.map: { @names[$_ - 32] }</syntaxhighlight>
{{out}}
<pre>Length 1: 70 candidates
Length 2: 172 candidates
Length 3: 494 candidates
Length 4: 1288 candidates
Length 5: 3235 candidates
Length 6: 7731 candidates
Length 7: 17628 candidates
Length 8: 37629 candidates
Length 9: 75122 candidates
Length 10: 139091 candidates
Length 11: 236679 candidates
Length 12: 367405 candidates
Length 13: 516210 candidates
Length 14: 650916 candidates
Length 15: 733915 candidates
Length 16: 727566 candidates
Length 17: 621835 candidates
Length 18: 446666 candidates
Length 19: 260862 candidates
Length 20: 119908 candidates
Length 21: 40296 candidates
Length 22: 10112 candidates
Length 23: 1248 candidates
Length of longest: 23
machamp petilil loudred darmanitan nosepass simisear rufflet trapinch heatmor registeel landorus starly yamask kricketune exeggcute emboar relicanth haxorus seaking girafarig gabite emolga audino</pre>
 
=={{header|REXX}}==
{{trans|ooRexx}}
===brute force version===
(This program is modeled after the ooRexx version, but with a bugfixed fixbug.)
<br><br>This REXX version allows a limit on the word scan (very useful for testing and debugging), and
<br>also has various speed optimizations.
<langsyntaxhighlight lang="rexx">/*REXX pgmprogram tofinds the find longest path of word's last-letter ──► tolast─letter 1st-letter───► first─letter. */
@='audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon cresselia croagunk darmanitan',
'deino emboar emolga exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur jellicent',
Line 2,895 ⟶ 4,208:
'remoraid rufflet sableye scolipede scrafty seaking sealeo silcoon simisear snivy snorlax spoink',
'starly tirtouga trapinch treecko tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask'
#= words(@); ig= 0; !.= 0; @.= /*nullify array and the longest path. */
#=words(@)
parse arg limit .; if limit\=='' then #=limit /*allow user to specify a scan limit. */
call build@.=; $$$= /*nullifybuild a stemmed array, andfrom longestthe @ pathlist*/
do iv=# by -1 for # /*buildscrub athe stemmed@ arraylist fromfor unusable words. list*/
parse var @.i=v F 2 '' -1 L /*obtain first and last letter of word(@,i).*/
if !.1.F>1 | !.9.L>1 then iterate end /*iis this a dead word?*/
soFar=0 say 'ignoring dead word:' @.v; ig= ig + 1; /*the initial maximum path length*/ @= delword(@, v, 1)
end do j=1/*v*/ for # /*delete dead word from @ ──┘ */
$$$= parse value @.1 @.j with @.j @ /*nullify the possible longest path.1 */
if ig\==0 then do; call build@; say; say 'ignoring' callig "dead word"s(ig).; scanner $$$,2say
parse value @.1 @.j with @.j @.1end
MP= 0; MPL= 0 end /*jthe initial Maximum Path Length. */
do j=1 for # /* ─ ─ ─ */
L=words($$$)
parse value @.1 @.j with @.j @.1; call scan $$$, 2
say 'Of' # "words," MP 'path's(MP) "have the maximum path length of" L'.'
parse value @.1 @.j with @.j @.1
say; say 'One example path of that length is:'
do m=1 for L; say left('',39) word($$$,m); end /*mj*/
g= words($$$)
exit /*stick a fork in it, we're done.*/
say 'Of' # "words," MP 'path's(MP) "have the maximum path length of" g'.'
/*──────────────────────────────────S subroutine────────────────────────*/
say; say 'One example path of that length is: ' word($$$, 1)
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1)
do m=2 to g; say left('', 36) word($$$, m)
/*──────────────────────────────────SCANNER subroutine (recursive)──────*/
scanner: procedure expose @. MP # soFar $$$; parse arg $$$,!; end _=!-1 /**/
lastChar=right(@._,1)exit 0 /*laststick a fork in it, char ofwe're penultimateall worddone. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
 
s: if arg(1)==1 then return arg(3); return word( arg(2) 's', 1) /*a pluralizer.*/
do i=! to # /*scan for the longest word path.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
if left(@.i,1)==lastChar then /*is the first-char = last-char? */
build@: do i=1 for #; @.i=word(@, i) /*build a stemmed array from the list. */
do
if !==soFar then MP=MP+1 F= left(@.i, 1); !.1.F= !.1.F + 1 /*bumpF: the maximum1st pathschar; counter!.1.F=count of 1st char*/
L=right(@.i, 1); else if!.9.L= !>soFar.9.L then+ do; $$$=@.1 /*L: last " !.9.L= " /*rebuild it " last " */
end /*i*/; do n=2 to !-1return
/*──────────────────────────────────────────────────────────────────────────────────────*/
$$$=$$$ @.n
scan: procedure expose @. # !. $$$ MP MPL; parse arg $$$,!; p=! - end /*n*/1
parse var @.p '' -1 LC /*obtain last character of $$$=$$$previous @.i /*add last. */
if !.1.LC==0 then return /*is this a dead─end word? MP=1; soFar=! /*new path. */
end /* [↓] PARSE obtains first char of @.i*/
do i=! to #; parse var @.i p 2 /*scan for the longest word path. */
parse value @.! @.i with @.i @.!
call scanner $$$,!+1 if p==LC then do /*recursiveis the scanfirst─character for longestlast─char? path*/
if !==MPL then MP= MP+1 /*bump the Maximum Paths Counter. */
parse value @.! @.i with @.i @.!
else if !>MPL then do; $$$=@.1 /*rebuild. */
end
do n=2 for !-2; $$$=$$$ @.n
end /*i*/
return /*exhausted this particular scan.* end /<*n*/lang>
$$$=$$$ @.i /*add last.*/
'''output'''
MP=1; MPL=! /*new path.*/
<pre style="overflow:scroll">
end
parse value @.! @.i with @.i @.!; call scan $$$, !+1
parse value @.! @.i with @.i @.!
end
end /*i*/; return /*exhausted this particular scan. */</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Of 70 words, 1248 paths have the maximum path length of 23.
 
One example path of that length 23 is: machamp
petilil
landorus
scrafty
yamask
kricketune
emboar
registeel
loudred
darmanitan
nosepass
simisear
relicanth
heatmor
rufflet
trapinch
haxorus
seaking
girafarig
gabite
exeggcute
emolga
audino
</pre>
 
===optimized version===
This optimized version has two major improvements:
::* &nbsp; removes dead words (words that cannot be used in a path)
::* &nbsp; stops scanning when a dead-end word is encountered.
<br>With the full list of words being used, there're are no dead words &nbsp; (but there are when a limit is used to shorten the list).
<br>In the &nbsp; '''scan''' &nbsp; subroutine, a check is made to see if the word being used is a dead-end word, and if so, the rest of
a limit is used to shorten the list).
<br>In the SCANrecursive subroutine, a checkscan is madeaborted toand see ifthe the next word being used is a dead-end word,scanned.
<br><br>The optimized version is around &nbsp; '''25%''' &nbsp; faster than the brute-force version.
<br>and if so, the rest of the recursive scan is aborted and the the next word is scanned.
<syntaxhighlight lang="rexx">/*REXX program finds the longest path of word's last─letter ───► first─letter. */
<br><br>The optimized version is around '''23%''' faster than the brute-force version.
<lang rexx>/*REXX pgm to find longest path of word's last-letter ──► to 1st-letter.*/
@='audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon cresselia croagunk darmanitan',
'deino emboar emolga exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur jellicent',
Line 2,980 ⟶ 4,299:
'remoraid rufflet sableye scolipede scrafty seaking sealeo silcoon simisear snivy snorlax spoink',
'starly tirtouga trapinch treecko tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask'
#= words(@); @.=; @s=@.; ig=0; og=0; !.=0 /*nullify array and the longest path. */
#=words(@)
parse arg limit .; if limit\=='' then #= limit /*allow user to specify a scan limit. */
call build@.=; $$$=; ig=0 /*nullifybuild a stemmed array andfrom longestthe @ path.list*/
do v=# by -1 for # /*scrub the @ list for unusable words. */
call build@.
parse var @.v doF v=# by2 '' -1 for #L /*scrubobtain first and listlast forletter unusuableof wordsword.*/
if !.1.F>1 | F= left(@!.v,9.L>1) then iterate /*first letter of the word. /*is this a dead word? */
say 'ignoring dead word:' L=right(@.v,1); /* lastig= ig + 1; " " @= "delword(@, v, " */1)
end /*v*/ if !.1.F>1 | !.9.L>1 then iterate /*is adelete dead word? from @ ──┘ */
#= words(@) @=delword(@,v,1) /*deleterecalculate fromthe number of words in @. */
do v=# by say-1 'ignorning deadfor word:'# /*scrub the @.v; list for stoppable ig=ig+1words.*/
parse var @.v endF 2 '' -1 L /*vobtain first and last letter of word.*/
if !.1.L>0 then iterate /*is this a stop word? */
if ig\==0 then do
call buildif @.v\=='' then say 'removing stop word:' @.v
say; og= og + 1; say 'ignoring' ig@= "dead word"sdelword(ig@, v, 1)'.'; say @s= @s @.v
end /*v*/ /*delete dead word from @ ──┘ */
end
soFar=0 /*the initial maximum path length*/
do j=1 for #
parse value @.1 @.j with @.j @.1
call scanner $$$,2
parse value @.1 @.j with @.j @.1
end /*j*/
g=words($$$)
say 'Of' # "words," MP 'path's(MP) "have the maximum path length of" g'.'
say; say 'One example path of that length is:'
 
if og\==0 then do; m=1 forcall gbuild@; say; say 'ignoring' og "stop /*display a list of wordsword"s(og). */
say 'stop words: ' @s; say
say left('',39) word($$$,m)
end /*m*/ end
exit$$$= /*sticknullify athe forkpossible inlongest path. it, we're done.*/
MP= 0; MPL= 0 /*the initial Maximum Path Length. */
/*──────────────────────────────────BUILD suroutine─────────────────────*/
build@.: !.=0; do ij=1 for # /*build a stemmed array from list ─ ─ ─ */
parse value @.i=word(1 @.j with @.j @.1; call scan $$$,i) 2
parse value F= left(@.i,1); @.j !.1.F=!.1.F+1 with /*count @.j 1st chars*/@.1
L=right(@.i,1); !.9.L=!.9.L+1end /*count last charsj*/
g= words($$$)
end /*i*/
say 'Of' # "words," MP 'path's(MP) "have the maximum path length of" g'.'
return
say; say 'One example path of that length is: ' word($$$, 1)
/*──────────────────────────────────S subroutine────────────────────────*/
do m=2 to g; say left('', 36) word($$$, m)
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1)
end /*m*/
/*──────────────────────────────────SCANNER subroutine (recursive)──────*/
exit /*stick a fork in it, we're all done. */
scanner: procedure expose @. MP # !. soFar $$$; parse arg $$$,!; _=!-1
/*──────────────────────────────────────────────────────────────────────────────────────*/
lastChar=right(@._,1) /*last char of penultimate word. */
s: if !.arg(1.lastchar)==01 then return arg(3); /*is this a dead-endreturn word( ?arg(2) 's', 1) /*a pluralizer.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
 
build@: do i=!1 tofor #; @.i= word(@, i) /*build a stemmed array /*scan forfrom the longestlist. word path.*/
if F= left(@.i, 1)==lastChar then; !.1.F= !.1.F + 1 /*isF: the first-1st char; !.1.F=count last-char?of 1st char*/
L= right(@.i, 1); !.9.L= !.9.L + 1 /*L: last " !.9.L= " " last " */
do
if !==soFar then MP=MP+1 end /*i*/; /*bump the maximum paths counter.*/return
/*──────────────────────────────────────────────────────────────────────────────────────*/
else if !>soFar then do; $$$=@.1 /*rebuild it*/
scan: procedure expose @. # !. $$$ MP MPL; parse arg $$$,!; do np=2 to ! - 1
parse var @.p '' -1 LC /*obtain last character of $$$=$$$previous @.n */
if !.1.LC==0 then return /*is this a dead─end word? end /*n*/
$$$=$$$ @.i /*add last.[↓] PARSE obtains first char of @.i*/
do i=! to #; parse var @.i p 2 /*scan for the longest word path. MP=1; soFar=! /*new path. */
if p==LC then do /*is endthe first─character ≡ last─char? */
if !==MPL then MP= MP+1 /*bump the Maximum Paths Counter. */
parse value @.! @.i with @.i @.!
call scanner $$$,!+1 /*recursive scan for longest path else if !>MPL then do; $$$= @.1 /*rebuild. */
do n=2 for !-2; $$$=$$$ @.n
parse value @.! @.i with @.i @.!
end /*n*/
end
$$$= $$$ @.i /*add last.*/
end /*i*/
return /*exhausted this particular scan MP=1; MPL=! /*new path.*/</lang>
end
'''output''' is the same as the brute force version.
parse value @.! @.i with @.i @.!; call scan $$$, !+1
parse value @.! @.i with @.i @.!
end
end /*i*/; return /*exhausted this particular scan. */</syntaxhighlight>
{{out|output|text=&nbsp; is the same as the brute force version.}}
<br><br>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
# Project : Last letter-first letter
 
ready = []
names = ["audino", "bagon", "baltoy", "banette",
"bidoof", "braviary", "bronzor", "carracosta", "charmeleon",
"cresselia", "croagunk", "darmanitan", "deino", "emboar",
"emolga", "exeggcute", "gabite", "girafarig", "gulpin",
"haxorus", "heatmor", "heatran", "ivysaur", "jellicent",
"jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba",
"loudred", "lumineon", "lunatone", "machamp", "magnezone",
"mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu",
"pinsir", "poliwrath", "poochyena", "porygon2", "porygonz",
"registeel", "relicanth", "remoraid", "rufflet", "sableye",
"scolipede", "scrafty", "seaking", "sealeo", "silcoon",
"simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga",
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix",
"wailord", "wartortle", "whismur", "wingull", "yamask"]
strbegin = "gabite"
strdir = "first"
nr = 1
add(ready,strbegin)
see strbegin + nl
while true
if strdir = "first"
strc = right(strbegin, 1)
flag = 1
nr = nr + 1
if nr <= len(names)
if left(names[nr],1) = strc
for n = 1 to len(ready)
if names[nr] = ready[n]
flag = 0
ok
next
if flag = 1
add(ready,names[nr])
see names[nr] + nl
strbegin = names[nr]
nr = 0
strdir = "last"
loop
ok
ok
ok
else
strc = right(strbegin, 1)
flag = 1
nr = nr + 1
if nr <= len(names)
if left(names[nr],1) = strc
for n = 1 to len(ready)
if names[nr] = ready[n]
flag = 0
ok
next
if flag = 1
add(ready,names[nr])
see names[nr] + nl
strbegin = names[nr]
nr = 0
strdir = "first"
loop
ok
ok
ok
ok
end
</syntaxhighlight>
Output:
<pre>
gabite
emboar
registeel
landorus
sableye
emolga
audino
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class LastL_FirstL
def initialize(names)
@names = names.dup
Line 3,084 ⟶ 4,480:
 
lf = LastL_FirstL.new(names)
lf.search</langsyntaxhighlight>
outputs
<pre>there are 2076396 possible sequences
Line 3,112 ⟶ 4,508:
22 emolga
23 audino</pre>
 
=={{header|Rust}}==
{{trans|Kotlin}}
<syntaxhighlight lang="rust">/// # Panics
///
/// If string is empty.
fn first_char(string: &str) -> char {
string.chars().next().unwrap()
}
 
/// # Panics
///
/// If string is empty.
fn first_and_last_char(string: &str) -> (char, char) {
(
first_char(string),
first_char(string.rmatches(|_: char| true).next().unwrap()),
)
}
 
struct Pokemon {
name: &'static str,
first: char,
last: char,
}
 
impl Pokemon {
fn new(name: &'static str) -> Pokemon {
let (first, last) = first_and_last_char(name);
Pokemon { name, first, last }
}
}
 
#[derive(Default)]
struct App {
max_path_length: usize,
max_path_length_count: usize,
max_path_example: Vec<&'static str>,
pokemon: Vec<Pokemon>,
}
 
impl App {
fn search(&mut self, offset: usize) {
if offset > self.max_path_length {
self.max_path_length = offset;
self.max_path_length_count = 1;
} else if offset == self.max_path_length {
self.max_path_length_count += 1;
self.max_path_example.clear();
self.max_path_example.extend(
self.pokemon[0..offset]
.iter()
.map(|Pokemon { name, .. }| *name),
);
}
 
let last_char = self.pokemon[offset - 1].last;
for i in offset..self.pokemon.len() {
if self.pokemon[i].first == last_char {
self.pokemon.swap(offset, i);
self.search(offset + 1);
self.pokemon.swap(offset, i);
}
}
}
}
 
fn main() {
let pokemon_names = [
"audino",
"bagon",
"baltoy",
"banette",
"bidoof",
"braviary",
"bronzor",
"carracosta",
"charmeleon",
"cresselia",
"croagunk",
"darmanitan",
"deino",
"emboar",
"emolga",
"exeggcute",
"gabite",
"girafarig",
"gulpin",
"haxorus",
"heatmor",
"heatran",
"ivysaur",
"jellicent",
"jumpluff",
"kangaskhan",
"kricketune",
"landorus",
"ledyba",
"loudred",
"lumineon",
"lunatone",
"machamp",
"magnezone",
"mamoswine",
"nosepass",
"petilil",
"pidgeotto",
"pikachu",
"pinsir",
"poliwrath",
"poochyena",
"porygon2",
"porygonz",
"registeel",
"relicanth",
"remoraid",
"rufflet",
"sableye",
"scolipede",
"scrafty",
"seaking",
"sealeo",
"silcoon",
"simisear",
"snivy",
"snorlax",
"spoink",
"starly",
"tirtouga",
"trapinch",
"treecko",
"tyrogue",
"vigoroth",
"vulpix",
"wailord",
"wartortle",
"whismur",
"wingull",
"yamask",
];
 
let mut app = App {
pokemon: pokemon_names
.iter()
.map(|name| Pokemon::new(name))
.collect(),
..App::default()
};
 
for i in 0..app.pokemon.len() {
app.pokemon.swap(0, i);
app.search(1);
app.pokemon.swap(0, i);
}
 
println!("Maximum path length: {}", app.max_path_length);
println!("Paths of that length: {}", app.max_path_length_count);
println!(
"Example path of that length: {}",
app.max_path_example.join(" "),
);
}
</syntaxhighlight>
Recommend you run as `release` or at least with `opt-level=1`
{{out}}
<pre>
Maximum path length: 23
Paths of that length: 1248
Example path of that length: machamp pinsir rufflet trapinch heatmor remoraid darmanitan nosepass starly yamask kricketune exeggcute emboar relicanth haxorus simisear registeel landorus seaking girafarig gabite emolga audino
</pre>
 
=={{header|Scala}}==
===Naive===
<syntaxhighlight lang="scala">object LastLetterFirstLetterNaive extends App {
def solve(names: Set[String]) = {
def extend(solutions: List[List[String]]): List[List[String]] = {
val more = solutions.flatMap{solution =>
val lastLetter = solution.head takeRight 1
(names -- solution).filter(_.take(1) equalsIgnoreCase lastLetter).map(_ :: solution)
}
if (more.isEmpty) solutions else extend(more)
}
 
extend(names.toList.map(List(_))).map(_.reverse)
}
 
val names70 = Set("audino", "bagon", "baltoy", "banette", "bidoof", "braviary", "bronzor", "carracosta", "charmeleon", "cresselia", "croagunk", "darmanitan", "deino", "emboar", "emolga", "exeggcute", "gabite", "girafarig", "gulpin", "haxorus", "heatmor", "heatran", "ivysaur", "jellicent", "jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba", "loudred", "lumineon", "lunatone", "machamp", "magnezone", "mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu", "pinsir", "poliwrath", "poochyena", "porygon2", "porygonz", "registeel", "relicanth", "remoraid", "rufflet", "sableye", "scolipede", "scrafty", "seaking", "sealeo", "silcoon", "simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga", "trapinch", "treecko", "tyrogue", "vigoroth", "vulpix", "wailord", "wartortle", "whismur", "wingull", "yamask")
 
val solutions = solve(names70)
println(s"Maximum path length: ${solutions.head.length}")
println(s"Paths of that length: ${solutions.size}")
println("Example path of that length:")
println(solutions.head.sliding(7,7).map(_.mkString(" ")).map(" "+_).mkString("\n"))
}</syntaxhighlight>
Output:
<pre>Maximum path length: 23
Paths of that length: 1248
Example path of that length:
machamp petilil loudred darmanitan nosepass snivy yamask
kricketune emboar rufflet trapinch heatmor relicanth haxorus
simisear registeel landorus seaking girafarig gabite exeggcute
emolga audino</pre>
===With Lookup Table (Faster)===
<syntaxhighlight lang="scala">object LastLetterFirstLetterLookup extends App {
def solve(names: Set[String]) = {
val transitions = {
val startsWith = names.groupBy(_.take(1).toLowerCase).withDefaultValue(Set.empty)
names.map{name => name -> startsWith(name.takeRight(1).toLowerCase)}.toMap
}
 
def extend(solutions: List[List[String]]): List[List[String]] =
solutions.flatMap{solution =>
(transitions(solution.head) -- solution).map(_ :: solution)
} match {
case Nil => solutions
case more => extend(more)
}
 
extend(names.toList.map(List(_))).map(_.reverse)
}
 
val names70 = Set("audino", "bagon", "baltoy", "banette", "bidoof", "braviary", "bronzor", "carracosta", "charmeleon", "cresselia", "croagunk", "darmanitan", "deino", "emboar", "emolga", "exeggcute", "gabite", "girafarig", "gulpin", "haxorus", "heatmor", "heatran", "ivysaur", "jellicent", "jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba", "loudred", "lumineon", "lunatone", "machamp", "magnezone", "mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu", "pinsir", "poliwrath", "poochyena", "porygon2", "porygonz", "registeel", "relicanth", "remoraid", "rufflet", "sableye", "scolipede", "scrafty", "seaking", "sealeo", "silcoon", "simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga", "trapinch", "treecko", "tyrogue", "vigoroth", "vulpix", "wailord", "wartortle", "whismur", "wingull", "yamask")
 
val solutions = solve(names70)
println(s"Maximum path length: ${solutions.head.length}")
println(s"Paths of that length: ${solutions.size}")
println("Example path of that length:")
println(solutions.head.sliding(7,7).map(_.mkString(" ")).map(" "+_).mkString("\n"))
}</syntaxhighlight>
===Parallelised With Lookup Table (Faster)===
<syntaxhighlight lang="scala">object LastLetterFirstLetterLookupParallel extends App {
def solve(names: Set[String]) = {
val transitions = {
val startsWith = names.groupBy(_.take(1).toLowerCase).withDefaultValue(Set.empty)
names.map{name => name -> startsWith(name.takeRight(1).toLowerCase)}.toMap
}
 
import scala.collection.parallel.immutable.ParSeq
def extend(solutions: ParSeq[List[String]]): ParSeq[List[String]] =
solutions.flatMap{solution =>
(transitions(solution.head) -- solution).map(_ :: solution)
} match {
case seq if seq.isEmpty => solutions
case more => extend(more)
}
 
extend(names.toList.map(List(_)).par).map(_.reverse)
}
 
val names70 = Set("audino", "bagon", "baltoy", "banette", "bidoof", "braviary", "bronzor", "carracosta", "charmeleon", "cresselia", "croagunk", "darmanitan", "deino", "emboar", "emolga", "exeggcute", "gabite", "girafarig", "gulpin", "haxorus", "heatmor", "heatran", "ivysaur", "jellicent", "jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba", "loudred", "lumineon", "lunatone", "machamp", "magnezone", "mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu", "pinsir", "poliwrath", "poochyena", "porygon2", "porygonz", "registeel", "relicanth", "remoraid", "rufflet", "sableye", "scolipede", "scrafty", "seaking", "sealeo", "silcoon", "simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga", "trapinch", "treecko", "tyrogue", "vigoroth", "vulpix", "wailord", "wartortle", "whismur", "wingull", "yamask")
 
val solutions = solve(names70)
println(s"Maximum path length: ${solutions.head.length}")
println(s"Paths of that length: ${solutions.size}")
println("Example path of that length:")
println(solutions.head.sliding(7,7).map(_.mkString(" ")).map(" "+_).mkString("\n"))
}</syntaxhighlight>
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
var integer: maxPathLength is 0;
Line 3,183 ⟶ 4,836:
writeln("paths of that length: " <& maxPathLengthCount lpad 4);
writeln("example path of that length:" <& maxPathExample);
end func;</langsyntaxhighlight>
 
Output:
Line 3,195 ⟶ 4,848:
simisear registeel landorus seaking girafarig
gabite emolga audino
</pre>
 
=={{header|Sidef}}==
{{trans|Perl}}
<syntaxhighlight lang="ruby">class LLFL(Array words) {
 
has f = Hash()
 
method init {
words.each {|w|
var m = w.match(/^(.).*(.)$/)
f{m[0]}{w} = m[1]
}
}
 
method longest_chain {
 
var stack = []
var longest = []
 
func poke(c) {
var h = f{c}
 
h.each_k { |word|
var v = h.delete(word)
stack.push(word)
longest[] = stack[] if (stack.len > longest.len)
__FUNC__(v) if f.exists(v)
stack.pop
h{word} = v
}
}
 
f.each_k { poke(_) }
return longest
}
}
 
var words = %w(
audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon
cresselia croagunk darmanitan deino emboar emolga exeggcute gabite
girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan
kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine
nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2
porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking
sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko
tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask
)
 
var obj = LLFL(words)
var longest = obj.longest_chain()
 
say "#{longest.len}: #{longest.join(' ')}"</syntaxhighlight>
{{out}}
<pre>
23: machamp petilil landorus scrafty yamask kricketune exeggcute emboar registeel loudred darmanitan nosepass simisear rufflet trapinch heatmor relicanth haxorus seaking girafarig gabite emolga audino
</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc search {path arcs} {
set solutions {}
set c [string index [lindex $path end] end]
Line 3,237 ⟶ 4,946:
}
set path [firstlast $names]
puts "Path (length: [llength $path]): $path"</langsyntaxhighlight>
Output:
<pre>
Line 3,245 ⟶ 4,954:
=={{header|Ursala}}==
 
<langsyntaxhighlight Ursalalang="ursala">#import std
 
mon =
Line 3,263 ⟶ 4,972:
#show+
 
example = ~&h poke mon</langsyntaxhighlight>output:
<pre>machamp
petilil
Line 3,288 ⟶ 4,997:
audino
</pre>
 
=={{header|VBScript}}==
{{trans|BBC BASIC}}
<syntaxhighlight lang="vb">' Last letter-first letter - VBScript - 11/03/2019
names = array( _
"audino", "bagon", "baltoy", "banette", _
"bidoof", "braviary", "bronzor", "carracosta", "charmeleon", _
"cresselia", "croagunk", "darmanitan", "deino", "emboar", _
"emolga", "exeggcute", "gabite", "girafarig", "gulpin", _
"haxorus", "heatmor", "heatran", "ivysaur", "jellicent", _
"jumpluff", "kangaskhan", "kricketune", "landorus", "ledyba", _
"loudred", "lumineon", "lunatone", "machamp", "magnezone", _
"mamoswine", "nosepass", "petilil", "pidgeotto", "pikachu", _
"pinsir", "poliwrath", "poochyena", "porygon2", "porygonz", _
"registeel", "relicanth", "remoraid", "rufflet", "sableye", _
"scolipede", "scrafty", "seaking", "sealeo", "silcoon", _
"simisear", "snivy", "snorlax", "spoink", "starly", "tirtouga", _
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix", _
"wailord", "wartortle", "whismur", "wingull", "yamask")
 
maxPathLength = 0
maxPathLengthCount = 0
maxPathExample = ""
t1=timer
 
For i = 0 To ubound(names)
'swap names(0), names(i)
temp=names(0): names(0)=names(i): names(i)=temp
Call lastfirst(names, 1)
'swap names(0), names(i)
temp=names(0): names(0)=names(i): names(i)=temp
Next 'i
buf = buf & "Maximum length = " & maxPathLength & vbCrLf
buf = buf & "Number of solutions with that length = " & maxPathLengthCount & vbCrLf
buf = buf & "One such solution: " & vbCrLf & maxPathExample & vbCrLf
t2=timer
MsgBox buf,,"Last letter-first letter - " & Int(t2-t1) & " sec"
 
Sub lastfirst(names, offset)
dim i, l
If offset > maxPathLength Then
maxPathLength = offset
maxPathLengthCount = 1
ElseIf offset = maxPathLength Then
maxPathLengthCount = maxPathLengthCount + 1
maxPathExample = ""
For i = 0 To offset-1
maxPathExample = maxPathExample & names(i) & vbCrLf
Next 'i
End If
l = Right(names(offset - 1),1)
For i = offset To ubound(names)
If Left(names(i),1) = l Then
'swap names(i), names(offset)
temp=names(offset): names(offset)=names(i): names(i)=temp
Call lastfirst(names, offset+1)
'swap names(i), names(offset)
temp=names(offset): names(offset)=names(i): names(i)=temp
End If
Next 'i
End Sub 'lastfirst </syntaxhighlight>
{{out}}
<pre>
Maximum length = 23
Number of solutions with that length = 1248
One such solution:
machamp
pinsir
rufflet
trapinch
heatmor
remoraid
darmanitan
nosepass
starly
yamask
kricketune
exeggcute
emboar
relicanth
haxorus
simisear
registeel
landorus
seaking
girafarig
gabite
emolga
audino
</pre>
Duration : 69 sec
 
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">var maxPathLength = 0
var maxPathLengthCount = 0
var maxPathExample = ""
 
var names = [
"audino", "bagon", "baltoy", "banette", "bidoof",
"braviary", "bronzor", "carracosta", "charmeleon", "cresselia",
"croagunk", "darmanitan", "deino", "emboar", "emolga",
"exeggcute", "gabite", "girafarig", "gulpin", "haxorus",
"heatmor", "heatran", "ivysaur", "jellicent", "jumpluff",
"kangaskhan", "kricketune", "landorus", "ledyba", "loudred",
"lumineon", "lunatone", "machamp", "magnezone", "mamoswine",
"nosepass", "petilil", "pidgeotto", "pikachu", "pinsir",
"poliwrath", "poochyena", "porygon2", "porygonz", "registeel",
"relicanth", "remoraid", "rufflet", "sableye", "scolipede",
"scrafty", "seaking", "sealeo", "silcoon", "simisear",
"snivy", "snorlax", "spoink", "starly", "tirtouga",
"trapinch", "treecko", "tyrogue", "vigoroth", "vulpix",
"wailord", "wartortle", "whismur", "wingull", "yamask"
]
 
var search // recursive function
search = Fn.new { |part, offset|
if (offset > maxPathLength) {
maxPathLength = offset
maxPathLengthCount = 1
} else if (offset == maxPathLength) {
maxPathLengthCount = maxPathLengthCount + 1
maxPathExample = ""
for (i in 0...offset) {
maxPathExample = maxPathExample + ((i % 5 == 0) ? "\n " : " ") + part[i]
}
}
var lastChar = part[offset - 1][-1]
for (i in offset...part.count) {
if (part[i][0] == lastChar) {
var tmp = names[offset]
names[offset] = names[i]
names[i] = tmp
search.call(names, offset + 1)
names[i] = names[offset]
names[offset] = tmp
}
}
}
 
for (i in 0...names.count) {
var tmp = names[0]
names[0] = names[i]
names[i] = tmp
search.call(names, 1)
names[i] = names[0]
names[0] = tmp
}
System.print("Maximum path length : %(maxPathLength)")
System.print("Paths of that length : %(maxPathLengthCount)")
System.print("Example path of that length : %(maxPathExample)")</syntaxhighlight>
 
{{out}}
<pre>
Maximum path length : 23
Paths of that length : 1248
Example path of that length :
machamp pinsir rufflet trapinch heatmor
remoraid darmanitan nosepass starly yamask
kricketune exeggcute emboar relicanth haxorus
simisear registeel landorus seaking girafarig
gabite emolga audino
</pre>
 
=={{header|Yabasic}}==
{{trans|Phix}}
<syntaxhighlight lang="yabasic">all$ = "audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon "
all$ = all$ + "cresselia croagunk darmanitan deino emboar emolga exeggcute gabite "
all$ = all$ + "girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan "
all$ = all$ + "kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine "
all$ = all$ + "nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2 "
all$ = all$ + "porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking "
all$ = all$ + "sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko "
all$ = all$ + "tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask"
 
dim word$(1)
lnames = token(all$, word$())
 
dim first(256), snext(lnames)
for i = 1 to lnames
ch = asc(left$(word$(i), 1))
if first(ch)=0 then
first(ch) = i
end if
for j=i+1 to lnames
if asc(left$(word$(j), 1))=ch then
snext(i) = j
break
end if
next
next
dim taken(lnames), best(lnames)
sub try(ch, last, n)
local nex, i
nex = first(ch)
while(nex <> 0)
if taken(nex)=0 then
taken(last) = nex
taken(nex) = -1
try(asc(right$(word$(nex), 1)),nex,n+1)
taken(last) = -1
taken(nex) = 0
end if
nex = snext(nex)
wend
if n>maxn then
bstart = tstart
for i = 1 to lnames
best(i) = taken(i)
next
maxn = n
count = 1
elsif n=maxn then
count = count + 1
end if
end sub
for i=1 to lnames
tstart = i
taken(i) = -1
try(asc(right$(word$(i), 1)),i,1)
taken(i) = 0
next
 
print "Runtime: ", peek("millisrunning")/1000, " seconds. Max length: ", maxn, ", found ", count, " of such, one of which is:\n"
do
print word$(bstart), " ";
bstart = best(bstart)
if bstart = -1 break
loop</syntaxhighlight>
 
=={{header|zkl}}==
Line 3,294 ⟶ 5,239:
No speed records were approached but 25sec seems fine for a one off walk the entire tree.
 
<langsyntaxhighlight lang="zkl">pokemon:=("audino bagon baltoy banette bidoof braviary "
"bronzor carracosta charmeleon cresselia croagunk darmanitan deino "
...
"whismur wingull yamask").split();
 
tree:=pokemon.pump(DDictionary(),'wrap(name){ //--> Hash("aB":("Bc","Bd",,,) )
T( name, pokemon.filter('wrap(nm){ name[-1]==nm[0] }) )
});
Line 3,315 ⟶ 5,260:
 
pokemon.reduce('wrap(np,name){ maxPath(walk(name,1,name,tree),np) },T(0,""))
.println();</langsyntaxhighlight>
{{out}}
<pre>
2,083

edits