Word Changer Reachability1P5: Word ChangerEach step of the Levenshtein distanceOne Letter SwapWrite a compact...
A Strange Latex Symbol
How to get a plain text file version of a CP/M .BAS (M-BASIC) program?
US visa is under administrative processing, I need the passport back ASAP
Document starts having heaps of errors in the middle, but the code doesn't have any problems in it
Is there really no use for MD5 anymore?
Exchange,swap or switch
Binary Numbers Magic Trick
What does it mean to express a gate in Dirac notation?
What is the strongest case that can be made in favour of the UK regaining some control over fishing policy after Brexit?
Is there an official tutorial for installing Ubuntu 18.04+ on a device with an SSD and an additional internal hard drive?
Is the 5 MB static resource size limit 5,242,880 bytes or 5,000,000 bytes?
How to stop co-workers from teasing me because I know Russian?
How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?
What was the first Intel x86 processor with "Base + Index * Scale + Displacement" addressing mode?
With a Canadian student visa, can I spend a night at Vancouver before continuing to Toronto?
What is the relationship between spectral sequences and obstruction theory?
Do I have to worry about players making “bad” choices on level up?
Does Gita support doctrine of eternal cycle of birth and death for evil people?
What do the phrase "Reeyan's seacrest" and the word "fraggle" mean in a sketch?
A Note on N!
How to have a sharp product image?
Packing rectangles: Does rotation ever help?
How can the Zone of Truth spell be defeated without the caster knowing?
Why do games have consumables?
Word Changer Reachability
1P5: Word ChangerEach step of the Levenshtein distanceOne Letter SwapWrite a compact spelling checkerAttraction Between WordsRead a crosswordOptimal cheating at BINGOWords with BlocksGif - Jif, Jif - GifUh, is it a haiku?Word Search on a TorusGenerate a Portmantout!
$begingroup$
Word changer is a game where you are trying to turn one word into another via single-character edits, with each step being its own word. For this challenge, edits may be replacements, insertions, or deletions. For example, WINNER → LOSER can be done with this route (there may be others):
WINNER
DINNER
DINER
DINE
LINE
LONE
LOSE
LOSER
Phrased another way, you must be able to reach one word from the other going only through other words at a Levenshtein distance of 1 each time.
Coding
You will be given a word list and two words and you must output a valid route from one word to the other if a route exists or a distinct constant value or consistent behavior if no route exists.
- You may assume that the input words are both in the word list
- The word list can be taken in via any convenient flat format.
- Lists, sets, tries, space-separated strings, and line-separated files are all valid (for instance), but a pre-computed graph of Levenshtein adjacency is not.
- The output route should include both input words, but which starts and ends doesn't matter.
- If no route is found, you can output a specific constant, a falsy value, empty list, throw an exception, exit with a nonzero code, or any other behavior that happens in finite time.
- The route does not need to be optimal
- Computational complexity does not matter, however your program must be provably guaranteed to terminate in a finite amount of time. (even if it would run beyond the heat death of the universe)
- You may assume all words are entirely composed of letters in the same case
Example Test Cases
- CAT → DOG; [CAT, DOG, COG, COT, FROG, GROG, BOG]
- CAT, COT, COG, DOG
- BATH → SHOWER; [BATH, SHOWER, HATH, HAT, BAT, SAT, SAW, SOW, SHOW, HOW]
- No Route Found
- BREAK → FIX; [BREAK, FIX, BEAK, BREAD, READ, BEAD, RED, BED, BAD, BID, FAD, FAX]
- BREAK, BREAD, BEAD, BAD, FAD, FAX, FIX
- BUILD → DESTROY; [BUILD, DESTROY, BUILT, GUILT, GUILD, GILD, GILL, BILL, DILL, FILL, DESTRUCT, STRUCTURE, CONSTRUCT]
- No Route Found
- CARD → BOARD; [CARD, BOARD, BARD]
- CARD, BARD, BOARD
- DEMON → ANGEL; [DEMON, ANGEL]
- No Route Found
- LAST → PAST; [LAST, PAST, BLAST, CAST, BLACK, GHOST, POST, BOAST]
- LAST, PAST
- INSERT → DELETE; This word list
- INSERT, INVERT, INVENT, INBENT, UNBENT, UNBEND, UNBIND, UNKIND, UNKING, INKING, IRKING, DIRKING, DARKING, DARLING, ARLING, AILING, SIRING, SERING, SERINE, NERINE, NERITE, CERITE, CERATE, DERATE, DELATE, DELETE
code-golf string decision-problem
$endgroup$
add a comment |
$begingroup$
Word changer is a game where you are trying to turn one word into another via single-character edits, with each step being its own word. For this challenge, edits may be replacements, insertions, or deletions. For example, WINNER → LOSER can be done with this route (there may be others):
WINNER
DINNER
DINER
DINE
LINE
LONE
LOSE
LOSER
Phrased another way, you must be able to reach one word from the other going only through other words at a Levenshtein distance of 1 each time.
Coding
You will be given a word list and two words and you must output a valid route from one word to the other if a route exists or a distinct constant value or consistent behavior if no route exists.
- You may assume that the input words are both in the word list
- The word list can be taken in via any convenient flat format.
- Lists, sets, tries, space-separated strings, and line-separated files are all valid (for instance), but a pre-computed graph of Levenshtein adjacency is not.
- The output route should include both input words, but which starts and ends doesn't matter.
- If no route is found, you can output a specific constant, a falsy value, empty list, throw an exception, exit with a nonzero code, or any other behavior that happens in finite time.
- The route does not need to be optimal
- Computational complexity does not matter, however your program must be provably guaranteed to terminate in a finite amount of time. (even if it would run beyond the heat death of the universe)
- You may assume all words are entirely composed of letters in the same case
Example Test Cases
- CAT → DOG; [CAT, DOG, COG, COT, FROG, GROG, BOG]
- CAT, COT, COG, DOG
- BATH → SHOWER; [BATH, SHOWER, HATH, HAT, BAT, SAT, SAW, SOW, SHOW, HOW]
- No Route Found
- BREAK → FIX; [BREAK, FIX, BEAK, BREAD, READ, BEAD, RED, BED, BAD, BID, FAD, FAX]
- BREAK, BREAD, BEAD, BAD, FAD, FAX, FIX
- BUILD → DESTROY; [BUILD, DESTROY, BUILT, GUILT, GUILD, GILD, GILL, BILL, DILL, FILL, DESTRUCT, STRUCTURE, CONSTRUCT]
- No Route Found
- CARD → BOARD; [CARD, BOARD, BARD]
- CARD, BARD, BOARD
- DEMON → ANGEL; [DEMON, ANGEL]
- No Route Found
- LAST → PAST; [LAST, PAST, BLAST, CAST, BLACK, GHOST, POST, BOAST]
- LAST, PAST
- INSERT → DELETE; This word list
- INSERT, INVERT, INVENT, INBENT, UNBENT, UNBEND, UNBIND, UNKIND, UNKING, INKING, IRKING, DIRKING, DARKING, DARLING, ARLING, AILING, SIRING, SERING, SERINE, NERINE, NERITE, CERITE, CERATE, DERATE, DELATE, DELETE
code-golf string decision-problem
$endgroup$
$begingroup$
Related, Related
$endgroup$
– Beefster
23 hours ago
1
$begingroup$
Can we output a list of valid routes or should it be one route?
$endgroup$
– Emigna
16 hours ago
add a comment |
$begingroup$
Word changer is a game where you are trying to turn one word into another via single-character edits, with each step being its own word. For this challenge, edits may be replacements, insertions, or deletions. For example, WINNER → LOSER can be done with this route (there may be others):
WINNER
DINNER
DINER
DINE
LINE
LONE
LOSE
LOSER
Phrased another way, you must be able to reach one word from the other going only through other words at a Levenshtein distance of 1 each time.
Coding
You will be given a word list and two words and you must output a valid route from one word to the other if a route exists or a distinct constant value or consistent behavior if no route exists.
- You may assume that the input words are both in the word list
- The word list can be taken in via any convenient flat format.
- Lists, sets, tries, space-separated strings, and line-separated files are all valid (for instance), but a pre-computed graph of Levenshtein adjacency is not.
- The output route should include both input words, but which starts and ends doesn't matter.
- If no route is found, you can output a specific constant, a falsy value, empty list, throw an exception, exit with a nonzero code, or any other behavior that happens in finite time.
- The route does not need to be optimal
- Computational complexity does not matter, however your program must be provably guaranteed to terminate in a finite amount of time. (even if it would run beyond the heat death of the universe)
- You may assume all words are entirely composed of letters in the same case
Example Test Cases
- CAT → DOG; [CAT, DOG, COG, COT, FROG, GROG, BOG]
- CAT, COT, COG, DOG
- BATH → SHOWER; [BATH, SHOWER, HATH, HAT, BAT, SAT, SAW, SOW, SHOW, HOW]
- No Route Found
- BREAK → FIX; [BREAK, FIX, BEAK, BREAD, READ, BEAD, RED, BED, BAD, BID, FAD, FAX]
- BREAK, BREAD, BEAD, BAD, FAD, FAX, FIX
- BUILD → DESTROY; [BUILD, DESTROY, BUILT, GUILT, GUILD, GILD, GILL, BILL, DILL, FILL, DESTRUCT, STRUCTURE, CONSTRUCT]
- No Route Found
- CARD → BOARD; [CARD, BOARD, BARD]
- CARD, BARD, BOARD
- DEMON → ANGEL; [DEMON, ANGEL]
- No Route Found
- LAST → PAST; [LAST, PAST, BLAST, CAST, BLACK, GHOST, POST, BOAST]
- LAST, PAST
- INSERT → DELETE; This word list
- INSERT, INVERT, INVENT, INBENT, UNBENT, UNBEND, UNBIND, UNKIND, UNKING, INKING, IRKING, DIRKING, DARKING, DARLING, ARLING, AILING, SIRING, SERING, SERINE, NERINE, NERITE, CERITE, CERATE, DERATE, DELATE, DELETE
code-golf string decision-problem
$endgroup$
Word changer is a game where you are trying to turn one word into another via single-character edits, with each step being its own word. For this challenge, edits may be replacements, insertions, or deletions. For example, WINNER → LOSER can be done with this route (there may be others):
WINNER
DINNER
DINER
DINE
LINE
LONE
LOSE
LOSER
Phrased another way, you must be able to reach one word from the other going only through other words at a Levenshtein distance of 1 each time.
Coding
You will be given a word list and two words and you must output a valid route from one word to the other if a route exists or a distinct constant value or consistent behavior if no route exists.
- You may assume that the input words are both in the word list
- The word list can be taken in via any convenient flat format.
- Lists, sets, tries, space-separated strings, and line-separated files are all valid (for instance), but a pre-computed graph of Levenshtein adjacency is not.
- The output route should include both input words, but which starts and ends doesn't matter.
- If no route is found, you can output a specific constant, a falsy value, empty list, throw an exception, exit with a nonzero code, or any other behavior that happens in finite time.
- The route does not need to be optimal
- Computational complexity does not matter, however your program must be provably guaranteed to terminate in a finite amount of time. (even if it would run beyond the heat death of the universe)
- You may assume all words are entirely composed of letters in the same case
Example Test Cases
- CAT → DOG; [CAT, DOG, COG, COT, FROG, GROG, BOG]
- CAT, COT, COG, DOG
- BATH → SHOWER; [BATH, SHOWER, HATH, HAT, BAT, SAT, SAW, SOW, SHOW, HOW]
- No Route Found
- BREAK → FIX; [BREAK, FIX, BEAK, BREAD, READ, BEAD, RED, BED, BAD, BID, FAD, FAX]
- BREAK, BREAD, BEAD, BAD, FAD, FAX, FIX
- BUILD → DESTROY; [BUILD, DESTROY, BUILT, GUILT, GUILD, GILD, GILL, BILL, DILL, FILL, DESTRUCT, STRUCTURE, CONSTRUCT]
- No Route Found
- CARD → BOARD; [CARD, BOARD, BARD]
- CARD, BARD, BOARD
- DEMON → ANGEL; [DEMON, ANGEL]
- No Route Found
- LAST → PAST; [LAST, PAST, BLAST, CAST, BLACK, GHOST, POST, BOAST]
- LAST, PAST
- INSERT → DELETE; This word list
- INSERT, INVERT, INVENT, INBENT, UNBENT, UNBEND, UNBIND, UNKIND, UNKING, INKING, IRKING, DIRKING, DARKING, DARLING, ARLING, AILING, SIRING, SERING, SERINE, NERINE, NERITE, CERITE, CERATE, DERATE, DELATE, DELETE
code-golf string decision-problem
code-golf string decision-problem
asked 23 hours ago
BeefsterBeefster
3,0231448
3,0231448
$begingroup$
Related, Related
$endgroup$
– Beefster
23 hours ago
1
$begingroup$
Can we output a list of valid routes or should it be one route?
$endgroup$
– Emigna
16 hours ago
add a comment |
$begingroup$
Related, Related
$endgroup$
– Beefster
23 hours ago
1
$begingroup$
Can we output a list of valid routes or should it be one route?
$endgroup$
– Emigna
16 hours ago
$begingroup$
Related, Related
$endgroup$
– Beefster
23 hours ago
$begingroup$
Related, Related
$endgroup$
– Beefster
23 hours ago
1
1
$begingroup$
Can we output a list of valid routes or should it be one route?
$endgroup$
– Emigna
16 hours ago
$begingroup$
Can we output a list of valid routes or should it be one route?
$endgroup$
– Emigna
16 hours ago
add a comment |
7 Answers
7
active
oldest
votes
$begingroup$
JavaScript (V8), 177 176 bytes
Takes input as (target)(source, list)
. Prints all possible routes. Or prints nothing if there's no solution.
t=>F=(s,l,p=[],d)=>s==t?print(p):l.map((S,i)=>(g=(m,n)=>m*n?1+Math.min(g(m-1,n),g(m,--n),g(--m,n)-(S[m]==s[n])):m+n)(S.length,s.length)^d||F(S,L=[...l],[...p,L.splice(i,1)],1))
Try it online!
Commented
t => // t = target string
F = ( // F is a recursive function taking:
s, // s = source string
l, // l[] = list of words
p = [], // p[] = path
d // d = expected Levenshtein distance between s and the
) => // next word (initially undefined, so coerced to 0)
s == t ? // if s is equal to t:
print(p) // stop recursion and print the path
: // else:
l.map((S, i) => // for each word S at index i in l[]:
( g = // g = recursive function computing the Levenshtein
(m, n) => // distance between S and s
m * n ? // if both m and n are not equal to 0:
1 + Math.min( // add 1 to the result + the minimum of:
g(m - 1, n), // g(m - 1, n)
g(m, --n), // g(m, n - 1)
g(--m, n) - // g(m - 1, n - 1), minus 1 if ...
(S[m] == s[n]) // ... S[m - 1] is equal to s[n - 1]
) // end of Math.min()
: // else:
m + n // return either m or n
)(S.length, s.length) // initial call to g with m = S.length, n = s.length
^ d || // unless the distance is not equal to d,
F( // do a recursive call to F with:
S, // the new source string S
L = [...l], // a copy L[] of l[]
[...p, L.splice(i, 1)], // the updated path (removes S from L[])
1 // an expected distance of 1
) // end of recursive call
) // end of map()
$endgroup$
add a comment |
$begingroup$
05AB1E, 23 21 bytes
Saved 2 bytes thanks to Kevin Cruijssen
怜€`ʒü.LP}.Δ¬²Qsθ³Q*
Try it online!
$endgroup$
$begingroup$
You can save 2 bytes by changingDævyœ«}
to怜€`
. (Not sure why both maps separately with€
works fine, butæεœ`}
does not btw, but it's the same byte-count anyway.)
$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
Too bad the product of[]
is1
instead of0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte:怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.
$endgroup$
– Emigna
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of justQ
. Not sure, though.
$endgroup$
– Kevin Cruijssen
12 hours ago
add a comment |
$begingroup$
Wolfram Language (Mathematica), 124 bytes
Join[#,Select[Flatten[Permutations/@Subsets@#3,1],s=#;t=#2;Union[EditDistance@@@Partition[Join[s,#,t],2,1]]=={1}&][[1]],#2]&
Try it online!
$endgroup$
add a comment |
$begingroup$
Python 2, 163 bytes
If a route is found, it is output to stderr and the program exits with exit code 1.
If there is no route, there is no output and the program terminates with exit code 0.
s,e,d=input();r=[[s]]
for x in r:t=x[-1];t==e>exit(x);r+=[x+[w]for w in d-set(x)for a,b in(t,w),(w,t)for i in range(len(b)*2)if a==b[:i/2]+a[i/2:][:i%2]+b[i/2+1:]]
Try it online!
$endgroup$
add a comment |
$begingroup$
Python 2, 155 bytes
f=lambda a,b,W,r=[]:a==b and r+[a]or reduce(lambda q,w:q or any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))and f(w,b,W-{a},r+[a]),W-{a},0)
Try it online!
Takes two words and a set of words as input; returns a (non-optimal) route if one exists as a list of strings, otherwise returns False.
This fragment:
any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))
is True
if and only if a==w
or a
has Levenshtein distance of 1
from w
.
$endgroup$
add a comment |
$begingroup$
Python 3, 217 214 212 bytes
d=lambda a,b:(min(d(a[1:],b[1:])+(a[0]!=b[0]),d(a[1:],b)+1,d(a,b[1:])+1)if b else len(a))if a else len(b)
def g(a,b,l,p=[]):
if a==b:yield[a]+p
for c in(a!=b)*l:
if(c in p)+d(a,c)==1:yield from g(c,b,l,[a]+p)
Try it online!
New contributor
$endgroup$
add a comment |
$begingroup$
Wolfram Language (Mathematica), 59 bytes
Select[Rule@@@#~Tuples~2,EditDistance@@#<2&]~FindPath~##2&;
Try it online!
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "200"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f184841%2fword-changer-reachability%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
JavaScript (V8), 177 176 bytes
Takes input as (target)(source, list)
. Prints all possible routes. Or prints nothing if there's no solution.
t=>F=(s,l,p=[],d)=>s==t?print(p):l.map((S,i)=>(g=(m,n)=>m*n?1+Math.min(g(m-1,n),g(m,--n),g(--m,n)-(S[m]==s[n])):m+n)(S.length,s.length)^d||F(S,L=[...l],[...p,L.splice(i,1)],1))
Try it online!
Commented
t => // t = target string
F = ( // F is a recursive function taking:
s, // s = source string
l, // l[] = list of words
p = [], // p[] = path
d // d = expected Levenshtein distance between s and the
) => // next word (initially undefined, so coerced to 0)
s == t ? // if s is equal to t:
print(p) // stop recursion and print the path
: // else:
l.map((S, i) => // for each word S at index i in l[]:
( g = // g = recursive function computing the Levenshtein
(m, n) => // distance between S and s
m * n ? // if both m and n are not equal to 0:
1 + Math.min( // add 1 to the result + the minimum of:
g(m - 1, n), // g(m - 1, n)
g(m, --n), // g(m, n - 1)
g(--m, n) - // g(m - 1, n - 1), minus 1 if ...
(S[m] == s[n]) // ... S[m - 1] is equal to s[n - 1]
) // end of Math.min()
: // else:
m + n // return either m or n
)(S.length, s.length) // initial call to g with m = S.length, n = s.length
^ d || // unless the distance is not equal to d,
F( // do a recursive call to F with:
S, // the new source string S
L = [...l], // a copy L[] of l[]
[...p, L.splice(i, 1)], // the updated path (removes S from L[])
1 // an expected distance of 1
) // end of recursive call
) // end of map()
$endgroup$
add a comment |
$begingroup$
JavaScript (V8), 177 176 bytes
Takes input as (target)(source, list)
. Prints all possible routes. Or prints nothing if there's no solution.
t=>F=(s,l,p=[],d)=>s==t?print(p):l.map((S,i)=>(g=(m,n)=>m*n?1+Math.min(g(m-1,n),g(m,--n),g(--m,n)-(S[m]==s[n])):m+n)(S.length,s.length)^d||F(S,L=[...l],[...p,L.splice(i,1)],1))
Try it online!
Commented
t => // t = target string
F = ( // F is a recursive function taking:
s, // s = source string
l, // l[] = list of words
p = [], // p[] = path
d // d = expected Levenshtein distance between s and the
) => // next word (initially undefined, so coerced to 0)
s == t ? // if s is equal to t:
print(p) // stop recursion and print the path
: // else:
l.map((S, i) => // for each word S at index i in l[]:
( g = // g = recursive function computing the Levenshtein
(m, n) => // distance between S and s
m * n ? // if both m and n are not equal to 0:
1 + Math.min( // add 1 to the result + the minimum of:
g(m - 1, n), // g(m - 1, n)
g(m, --n), // g(m, n - 1)
g(--m, n) - // g(m - 1, n - 1), minus 1 if ...
(S[m] == s[n]) // ... S[m - 1] is equal to s[n - 1]
) // end of Math.min()
: // else:
m + n // return either m or n
)(S.length, s.length) // initial call to g with m = S.length, n = s.length
^ d || // unless the distance is not equal to d,
F( // do a recursive call to F with:
S, // the new source string S
L = [...l], // a copy L[] of l[]
[...p, L.splice(i, 1)], // the updated path (removes S from L[])
1 // an expected distance of 1
) // end of recursive call
) // end of map()
$endgroup$
add a comment |
$begingroup$
JavaScript (V8), 177 176 bytes
Takes input as (target)(source, list)
. Prints all possible routes. Or prints nothing if there's no solution.
t=>F=(s,l,p=[],d)=>s==t?print(p):l.map((S,i)=>(g=(m,n)=>m*n?1+Math.min(g(m-1,n),g(m,--n),g(--m,n)-(S[m]==s[n])):m+n)(S.length,s.length)^d||F(S,L=[...l],[...p,L.splice(i,1)],1))
Try it online!
Commented
t => // t = target string
F = ( // F is a recursive function taking:
s, // s = source string
l, // l[] = list of words
p = [], // p[] = path
d // d = expected Levenshtein distance between s and the
) => // next word (initially undefined, so coerced to 0)
s == t ? // if s is equal to t:
print(p) // stop recursion and print the path
: // else:
l.map((S, i) => // for each word S at index i in l[]:
( g = // g = recursive function computing the Levenshtein
(m, n) => // distance between S and s
m * n ? // if both m and n are not equal to 0:
1 + Math.min( // add 1 to the result + the minimum of:
g(m - 1, n), // g(m - 1, n)
g(m, --n), // g(m, n - 1)
g(--m, n) - // g(m - 1, n - 1), minus 1 if ...
(S[m] == s[n]) // ... S[m - 1] is equal to s[n - 1]
) // end of Math.min()
: // else:
m + n // return either m or n
)(S.length, s.length) // initial call to g with m = S.length, n = s.length
^ d || // unless the distance is not equal to d,
F( // do a recursive call to F with:
S, // the new source string S
L = [...l], // a copy L[] of l[]
[...p, L.splice(i, 1)], // the updated path (removes S from L[])
1 // an expected distance of 1
) // end of recursive call
) // end of map()
$endgroup$
JavaScript (V8), 177 176 bytes
Takes input as (target)(source, list)
. Prints all possible routes. Or prints nothing if there's no solution.
t=>F=(s,l,p=[],d)=>s==t?print(p):l.map((S,i)=>(g=(m,n)=>m*n?1+Math.min(g(m-1,n),g(m,--n),g(--m,n)-(S[m]==s[n])):m+n)(S.length,s.length)^d||F(S,L=[...l],[...p,L.splice(i,1)],1))
Try it online!
Commented
t => // t = target string
F = ( // F is a recursive function taking:
s, // s = source string
l, // l[] = list of words
p = [], // p[] = path
d // d = expected Levenshtein distance between s and the
) => // next word (initially undefined, so coerced to 0)
s == t ? // if s is equal to t:
print(p) // stop recursion and print the path
: // else:
l.map((S, i) => // for each word S at index i in l[]:
( g = // g = recursive function computing the Levenshtein
(m, n) => // distance between S and s
m * n ? // if both m and n are not equal to 0:
1 + Math.min( // add 1 to the result + the minimum of:
g(m - 1, n), // g(m - 1, n)
g(m, --n), // g(m, n - 1)
g(--m, n) - // g(m - 1, n - 1), minus 1 if ...
(S[m] == s[n]) // ... S[m - 1] is equal to s[n - 1]
) // end of Math.min()
: // else:
m + n // return either m or n
)(S.length, s.length) // initial call to g with m = S.length, n = s.length
^ d || // unless the distance is not equal to d,
F( // do a recursive call to F with:
S, // the new source string S
L = [...l], // a copy L[] of l[]
[...p, L.splice(i, 1)], // the updated path (removes S from L[])
1 // an expected distance of 1
) // end of recursive call
) // end of map()
edited 17 hours ago
answered 18 hours ago
ArnauldArnauld
82.4k798339
82.4k798339
add a comment |
add a comment |
$begingroup$
05AB1E, 23 21 bytes
Saved 2 bytes thanks to Kevin Cruijssen
怜€`ʒü.LP}.Δ¬²Qsθ³Q*
Try it online!
$endgroup$
$begingroup$
You can save 2 bytes by changingDævyœ«}
to怜€`
. (Not sure why both maps separately with€
works fine, butæεœ`}
does not btw, but it's the same byte-count anyway.)
$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
Too bad the product of[]
is1
instead of0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte:怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.
$endgroup$
– Emigna
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of justQ
. Not sure, though.
$endgroup$
– Kevin Cruijssen
12 hours ago
add a comment |
$begingroup$
05AB1E, 23 21 bytes
Saved 2 bytes thanks to Kevin Cruijssen
怜€`ʒü.LP}.Δ¬²Qsθ³Q*
Try it online!
$endgroup$
$begingroup$
You can save 2 bytes by changingDævyœ«}
to怜€`
. (Not sure why both maps separately with€
works fine, butæεœ`}
does not btw, but it's the same byte-count anyway.)
$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
Too bad the product of[]
is1
instead of0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte:怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.
$endgroup$
– Emigna
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of justQ
. Not sure, though.
$endgroup$
– Kevin Cruijssen
12 hours ago
add a comment |
$begingroup$
05AB1E, 23 21 bytes
Saved 2 bytes thanks to Kevin Cruijssen
怜€`ʒü.LP}.Δ¬²Qsθ³Q*
Try it online!
$endgroup$
05AB1E, 23 21 bytes
Saved 2 bytes thanks to Kevin Cruijssen
怜€`ʒü.LP}.Δ¬²Qsθ³Q*
Try it online!
edited 12 hours ago
answered 16 hours ago
EmignaEmigna
48.4k434147
48.4k434147
$begingroup$
You can save 2 bytes by changingDævyœ«}
to怜€`
. (Not sure why both maps separately with€
works fine, butæεœ`}
does not btw, but it's the same byte-count anyway.)
$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
Too bad the product of[]
is1
instead of0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte:怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.
$endgroup$
– Emigna
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of justQ
. Not sure, though.
$endgroup$
– Kevin Cruijssen
12 hours ago
add a comment |
$begingroup$
You can save 2 bytes by changingDævyœ«}
to怜€`
. (Not sure why both maps separately with€
works fine, butæεœ`}
does not btw, but it's the same byte-count anyway.)
$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
Too bad the product of[]
is1
instead of0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte:怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.
$endgroup$
– Emigna
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of justQ
. Not sure, though.
$endgroup$
– Kevin Cruijssen
12 hours ago
$begingroup$
You can save 2 bytes by changing
Dævyœ«}
to 怜€`
. (Not sure why both maps separately with €
works fine, but æεœ`}
does not btw, but it's the same byte-count anyway.)$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
You can save 2 bytes by changing
Dævyœ«}
to 怜€`
. (Not sure why both maps separately with €
works fine, but æεœ`}
does not btw, but it's the same byte-count anyway.)$endgroup$
– Kevin Cruijssen
14 hours ago
$begingroup$
Too bad the product of
[]
is 1
instead of 0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of 0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte: 怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
Too bad the product of
[]
is 1
instead of 0
(not too surprising, though) or that an equal check with an empty list apparently results in an empty list instead of 0
(this one I see as a bug..).. Otherwise you could have combined the filter and find_first to save another byte: 怜€`.Δü.LPy¬²Qsθ³QP
$endgroup$
– Kevin Cruijssen
13 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using
€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.$endgroup$
– Emigna
12 hours ago
$begingroup$
@KevinCruijssen: Thanks! Not sure why I didn't think of using
€
. I think the equal check results in an empty list due to vectorization. Maybe there should be a special case for the empty list, but maybe that would be unexpected in other cases.$endgroup$
– Emigna
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of just
Q
. Not sure, though.$endgroup$
– Kevin Cruijssen
12 hours ago
$begingroup$
Yeah, I indeed realized it's due to vectorization after I made my comment. I mentioned it in the 05AB1E chat. But maybe this special case for empty lists would be beneficial for almost all vectorization usages instead of just
Q
. Not sure, though.$endgroup$
– Kevin Cruijssen
12 hours ago
add a comment |
$begingroup$
Wolfram Language (Mathematica), 124 bytes
Join[#,Select[Flatten[Permutations/@Subsets@#3,1],s=#;t=#2;Union[EditDistance@@@Partition[Join[s,#,t],2,1]]=={1}&][[1]],#2]&
Try it online!
$endgroup$
add a comment |
$begingroup$
Wolfram Language (Mathematica), 124 bytes
Join[#,Select[Flatten[Permutations/@Subsets@#3,1],s=#;t=#2;Union[EditDistance@@@Partition[Join[s,#,t],2,1]]=={1}&][[1]],#2]&
Try it online!
$endgroup$
add a comment |
$begingroup$
Wolfram Language (Mathematica), 124 bytes
Join[#,Select[Flatten[Permutations/@Subsets@#3,1],s=#;t=#2;Union[EditDistance@@@Partition[Join[s,#,t],2,1]]=={1}&][[1]],#2]&
Try it online!
$endgroup$
Wolfram Language (Mathematica), 124 bytes
Join[#,Select[Flatten[Permutations/@Subsets@#3,1],s=#;t=#2;Union[EditDistance@@@Partition[Join[s,#,t],2,1]]=={1}&][[1]],#2]&
Try it online!
edited 15 hours ago
answered 23 hours ago
J42161217J42161217
14.5k21354
14.5k21354
add a comment |
add a comment |
$begingroup$
Python 2, 163 bytes
If a route is found, it is output to stderr and the program exits with exit code 1.
If there is no route, there is no output and the program terminates with exit code 0.
s,e,d=input();r=[[s]]
for x in r:t=x[-1];t==e>exit(x);r+=[x+[w]for w in d-set(x)for a,b in(t,w),(w,t)for i in range(len(b)*2)if a==b[:i/2]+a[i/2:][:i%2]+b[i/2+1:]]
Try it online!
$endgroup$
add a comment |
$begingroup$
Python 2, 163 bytes
If a route is found, it is output to stderr and the program exits with exit code 1.
If there is no route, there is no output and the program terminates with exit code 0.
s,e,d=input();r=[[s]]
for x in r:t=x[-1];t==e>exit(x);r+=[x+[w]for w in d-set(x)for a,b in(t,w),(w,t)for i in range(len(b)*2)if a==b[:i/2]+a[i/2:][:i%2]+b[i/2+1:]]
Try it online!
$endgroup$
add a comment |
$begingroup$
Python 2, 163 bytes
If a route is found, it is output to stderr and the program exits with exit code 1.
If there is no route, there is no output and the program terminates with exit code 0.
s,e,d=input();r=[[s]]
for x in r:t=x[-1];t==e>exit(x);r+=[x+[w]for w in d-set(x)for a,b in(t,w),(w,t)for i in range(len(b)*2)if a==b[:i/2]+a[i/2:][:i%2]+b[i/2+1:]]
Try it online!
$endgroup$
Python 2, 163 bytes
If a route is found, it is output to stderr and the program exits with exit code 1.
If there is no route, there is no output and the program terminates with exit code 0.
s,e,d=input();r=[[s]]
for x in r:t=x[-1];t==e>exit(x);r+=[x+[w]for w in d-set(x)for a,b in(t,w),(w,t)for i in range(len(b)*2)if a==b[:i/2]+a[i/2:][:i%2]+b[i/2+1:]]
Try it online!
edited 2 hours ago
answered 3 hours ago
ovsovs
19.6k21161
19.6k21161
add a comment |
add a comment |
$begingroup$
Python 2, 155 bytes
f=lambda a,b,W,r=[]:a==b and r+[a]or reduce(lambda q,w:q or any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))and f(w,b,W-{a},r+[a]),W-{a},0)
Try it online!
Takes two words and a set of words as input; returns a (non-optimal) route if one exists as a list of strings, otherwise returns False.
This fragment:
any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))
is True
if and only if a==w
or a
has Levenshtein distance of 1
from w
.
$endgroup$
add a comment |
$begingroup$
Python 2, 155 bytes
f=lambda a,b,W,r=[]:a==b and r+[a]or reduce(lambda q,w:q or any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))and f(w,b,W-{a},r+[a]),W-{a},0)
Try it online!
Takes two words and a set of words as input; returns a (non-optimal) route if one exists as a list of strings, otherwise returns False.
This fragment:
any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))
is True
if and only if a==w
or a
has Levenshtein distance of 1
from w
.
$endgroup$
add a comment |
$begingroup$
Python 2, 155 bytes
f=lambda a,b,W,r=[]:a==b and r+[a]or reduce(lambda q,w:q or any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))and f(w,b,W-{a},r+[a]),W-{a},0)
Try it online!
Takes two words and a set of words as input; returns a (non-optimal) route if one exists as a list of strings, otherwise returns False.
This fragment:
any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))
is True
if and only if a==w
or a
has Levenshtein distance of 1
from w
.
$endgroup$
Python 2, 155 bytes
f=lambda a,b,W,r=[]:a==b and r+[a]or reduce(lambda q,w:q or any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))and f(w,b,W-{a},r+[a]),W-{a},0)
Try it online!
Takes two words and a set of words as input; returns a (non-optimal) route if one exists as a list of strings, otherwise returns False.
This fragment:
any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))
is True
if and only if a==w
or a
has Levenshtein distance of 1
from w
.
edited 41 mins ago
answered 1 hour ago
Chas BrownChas Brown
5,2591523
5,2591523
add a comment |
add a comment |
$begingroup$
Python 3, 217 214 212 bytes
d=lambda a,b:(min(d(a[1:],b[1:])+(a[0]!=b[0]),d(a[1:],b)+1,d(a,b[1:])+1)if b else len(a))if a else len(b)
def g(a,b,l,p=[]):
if a==b:yield[a]+p
for c in(a!=b)*l:
if(c in p)+d(a,c)==1:yield from g(c,b,l,[a]+p)
Try it online!
New contributor
$endgroup$
add a comment |
$begingroup$
Python 3, 217 214 212 bytes
d=lambda a,b:(min(d(a[1:],b[1:])+(a[0]!=b[0]),d(a[1:],b)+1,d(a,b[1:])+1)if b else len(a))if a else len(b)
def g(a,b,l,p=[]):
if a==b:yield[a]+p
for c in(a!=b)*l:
if(c in p)+d(a,c)==1:yield from g(c,b,l,[a]+p)
Try it online!
New contributor
$endgroup$
add a comment |
$begingroup$
Python 3, 217 214 212 bytes
d=lambda a,b:(min(d(a[1:],b[1:])+(a[0]!=b[0]),d(a[1:],b)+1,d(a,b[1:])+1)if b else len(a))if a else len(b)
def g(a,b,l,p=[]):
if a==b:yield[a]+p
for c in(a!=b)*l:
if(c in p)+d(a,c)==1:yield from g(c,b,l,[a]+p)
Try it online!
New contributor
$endgroup$
Python 3, 217 214 212 bytes
d=lambda a,b:(min(d(a[1:],b[1:])+(a[0]!=b[0]),d(a[1:],b)+1,d(a,b[1:])+1)if b else len(a))if a else len(b)
def g(a,b,l,p=[]):
if a==b:yield[a]+p
for c in(a!=b)*l:
if(c in p)+d(a,c)==1:yield from g(c,b,l,[a]+p)
Try it online!
New contributor
edited 8 hours ago
New contributor
answered 9 hours ago
movaticamovatica
514
514
New contributor
New contributor
add a comment |
add a comment |
$begingroup$
Wolfram Language (Mathematica), 59 bytes
Select[Rule@@@#~Tuples~2,EditDistance@@#<2&]~FindPath~##2&;
Try it online!
$endgroup$
add a comment |
$begingroup$
Wolfram Language (Mathematica), 59 bytes
Select[Rule@@@#~Tuples~2,EditDistance@@#<2&]~FindPath~##2&;
Try it online!
$endgroup$
add a comment |
$begingroup$
Wolfram Language (Mathematica), 59 bytes
Select[Rule@@@#~Tuples~2,EditDistance@@#<2&]~FindPath~##2&;
Try it online!
$endgroup$
Wolfram Language (Mathematica), 59 bytes
Select[Rule@@@#~Tuples~2,EditDistance@@#<2&]~FindPath~##2&;
Try it online!
answered 2 hours ago
attinatattinat
63917
63917
add a comment |
add a comment |
If this is an answer to a challenge…
…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.
…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.
More generally…
…Please make sure to answer the question and provide sufficient detail.
…Avoid asking for help, clarification or responding to other answers (use comments instead).
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f184841%2fword-changer-reachability%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Related, Related
$endgroup$
– Beefster
23 hours ago
1
$begingroup$
Can we output a list of valid routes or should it be one route?
$endgroup$
– Emigna
16 hours ago