Output an Anagram! No Not That One!

28

3

Given a list of unique strings that are anagrams of each other, output an anagram of those words that is different from each word in the list.

The strings will be alphanumeric, and there is guaranteed to be a valid anagram.

The program or function can, but doesn't have to be non-deterministic, meaning given the same input, multiple running a of the code can yield different outputs, as long as every possible output is a valid one.

Test Cases

[Input] -> Possible output
-----------------
[ab] -> ba
[aba, aab] -> baa
[123, 132, 231, 312, 321] -> 213
[hq999, 9h9q9, 9qh99] -> 999hq
[abcde123, ab3e1cd2, 321edbac, bcda1e23] -> ba213ecd

MildlyMilquetoast

Posted 2017-11-14T03:24:11.410

Reputation: 2 907

Answers

20

Python 3, 64 bytes

lambda a:[*{*permutations(a[0])}-{*a}][0]
from itertools import*

Try it online!

Mr. Xcoder

Posted 2017-11-14T03:24:11.410

Reputation: 39 774

4But is itertools ever the answer? – MildlyMilquetoast – 2017-11-14T06:44:07.353

@MistahFiggins Nominated

– Mr. Xcoder – 2017-11-14T09:46:02.523

@Mr.Xcoder before 22 July 2015 – Stan Strum – 2017-11-14T15:24:20.377

@StanStrum I just mentioned it, I am aware of that restriction. As Stewie said...

– Mr. Xcoder – 2017-11-14T15:25:09.230

@Mr.Xcoder didn’t see that, cool! – Stan Strum – 2017-11-14T15:25:52.853

If there a reason the import is after the lambda? – jpmc26 – 2017-11-14T21:26:00.940

1@jpmc26 Yes, this way you can put f=\ in the Try it Online header and leave the function anonymous, while not affecting the automatic TiO byte counter – Mr. Xcoder – 2017-11-14T21:27:06.517

Nifty. Thanks for answering. – jpmc26 – 2017-11-14T21:37:28.170

Great submission. I'd be interested to know if there's a shorter non-itertools solution. random string generation or sort with a random key would all be longer than your code. – Eric Duminil – 2017-11-15T12:33:31.063

9

05AB1E, 5 bytes

нœ¹мà

Try it online!

Explanation

нœ¹мà

н     // Get the first element of the input list
 œ    // Generate all permutations
  ¹   // Push the input again
   м  // In the permutations list, replace all strings that
      //   are in the input list with empty strings
    à // Pick the string with the greatest lexicographic
      //   index (in this case a non-empty string)

user72349

Posted 2017-11-14T03:24:11.410

Reputation:

7

Pyth, 5 bytes

h-.ph

Try it online!

Explanation

h-.ph
    h    First string in [the input]
  .p     All permutations
 -       Remove those in [the input]
h        First element.

notjagan

Posted 2017-11-14T03:24:11.410

Reputation: 4 011

4

Jelly, 6 bytes

XŒ!ḟµḢ

Try it online!

1 byte more than the 05AB1E and the Pyth answer.

Explanation:

XŒ!ḟµḢ   Main program.
 Œ!      All permutation of...
X        any element from the word list.
   ḟ     Filter out (remove) all the elements in the original word list.
    µ    With the filtered-out list,
     Ḣ   pick the first element.

I chosen X because it is the shortest way I know to pick any element from the list without altering the list ( and doesn't work, ḷ/ and ṛ/ is longer), and it happens to cause some randomness.

The µ here is pretty redundant, but without it, the would be paired with the , and it is interpreted as "filter out the head of the input", which is not what I need here (what I need is "filter out the input, and get the head").

user202729

Posted 2017-11-14T03:24:11.410

Reputation: 14 620

4

Haskell, 58 bytes

-1 byte and a fix thanks to Laikoni.

import Data.List
f l=[i|i<-permutations$l!!0,all(/=i)l]!!0

Try it online!

It's probably not worth importing Data.List for permutations but eh.

totallyhuman

Posted 2017-11-14T03:24:11.410

Reputation: 15 378

1You can save a byte with notElem. i would be surprised if someone finds a permutation function which beats the import, my shortest approach is 60 bytes vs. the 29 bytes of the import. – Laikoni – 2017-11-14T12:54:53.293

1Here is a 43 bytes permutation function, but only for duplicate free lists. – Laikoni – 2017-11-14T12:57:17.907

1Also your solution is currently not working because $ is missing before l!!0. – Laikoni – 2017-11-14T12:59:18.113

4

Javascript, 118 Bytes

function f(a){s=a[0];while(a.indexOf(s)!=-1)s=s.split("").sort(function(){return .5-Math.random()).join("")};return s}

uses a bad randomizer to iterate over each "random" permutation.

Probably provably wrong but afaik the bad randomizer just means we wont get true randomness, but will still get every permutation.

Seems to work on all cases in chrome for me but apparently due to undefined behaviour in this sort abuse, it can not work in some browsers.

(Probably very ungolfed feel free to improve it in your own solutions)

80 bytes

Thanks to pirateBay's comment -a lot of bytes

-4 bytes thanks to Rick

f=a=>eval('s=[...a[0]].sort(()=>.5-Math.random()).join``;a.indexOf(s)<0?s:f(a)')

Imme

Posted 2017-11-14T03:24:11.410

Reputation: 41

FYI arrow functions are allowed (for example a=>b instead of function(a){return b}). It saves a lot of bytes. – None – 2017-11-14T15:24:43.523

Wow... that'll save quite a few bytes. – Imme – 2017-11-14T15:49:31.283

s.split("") can be [...s]. Also join("") can be `join``` – Rick Hitchcock – 2017-11-14T16:05:42.880

@ThePirateBay i was afraid that would be the case, but why is that? (im aware that sort is not fully random,but all sequences SHOULD be possible) – Imme – 2017-11-14T16:12:32.320

@Imme. Here is 87 bytes working version. Notice that your sort function never returns 0 (or at least extremely rare), that's why it didn't work.

– None – 2017-11-14T16:18:40.107

@ThePirateBay Im going with extremely rare. You should post that as your own, quite different from mine already. I'll recheck and mark it wrong in a few hours. – Imme – 2017-11-14T16:24:19.127

3

Ruby, 46 bytes

->l{(l[0].chars.permutation.map(&:join)-l)[0]}

Try it online!

G B

Posted 2017-11-14T03:24:11.410

Reputation: 11 099

3

Brachylog, 7 bytes

hp.¬∈?∧

Try it online!

Explanation

hp.        The Output is a permutation of the first element of the Input
  .¬∈?     The Output is not a member of the Input
      ∧    (Disable implicit Input = Output)

Fatalize

Posted 2017-11-14T03:24:11.410

Reputation: 32 976

3

Japt, 7 6 bytes

-1 byte thanks to @Shaggy

á kN ö

Try it online!

Takes input strings as several inputs instead of as an array. Outputs a random permutation; switch ö to g to get the first one instead.

Explanation

á kN ö  Implicit input: N = array of input strings
á       Get all permutations of the first input string
  kN    Remove all input strings from those
     ö  Get a random element from the array. Implicit output

Justin Mariner

Posted 2017-11-14T03:24:11.410

Reputation: 4 746

Nuts, you beat me to it. You could take input as individual strings and save a byte with á kN ö. – Shaggy – 2017-11-14T14:50:55.017

@Shaggy That's a great way to get the first input item, I'll have to remember that. Thanks! – Justin Mariner – 2017-11-14T18:43:15.120

3

Mathematica, 57 bytes

non-deterministic

(While[!FreeQ[#,s=""<>RandomSample@Characters@#&@@#]];s)&

Try it online!

Mathematica, 56 bytes

deterministic

#&@@Complement[""<>#&/@Permutations@Characters@#&@@#,#]&

Try it online!

J42161217

Posted 2017-11-14T03:24:11.410

Reputation: 15 931

2

Python 3, 78 bytes

lambda a:[x for x in permutations(a[0])if~-(x in a)][0]
from itertools import*

Try it online!

-1 byte thanks to Mr. Xcoder

HyperNeutrino

Posted 2017-11-14T03:24:11.410

Reputation: 26 575

if x not in a is if~-(x in a) for 178 – Mr. Xcoder – 2017-11-14T05:14:35.300

@Mr.Xcoder. You mean 78, right? – None – 2017-11-14T05:22:03.537

@ThePirateBay Yes, I do... Whoops! – Mr. Xcoder – 2017-11-14T05:22:34.507

1

How about 66 bytes?

– NieDzejkob – 2017-11-14T12:58:18.317

1@NieDzejkob That's impressively shorter. You should post your own if you want – HyperNeutrino – 2017-11-14T12:59:25.147

@HyperNeutrino that's a simple golf based on your answer, but now I noticed that Mr. Xcoder's answer uses the same trick, but with [*s][0] instead of (s).pop()for 64 bytes. – NieDzejkob – 2017-11-14T13:01:43.653

@NieDzejkob oh yeah, I see it there now. Yeah, I'll keep mine in its current state because I don't really need to golf it down any further (and it would pretty much just be his version :P) – HyperNeutrino – 2017-11-14T13:03:55.373

2

MATL, 15, 13, 12 bytes

1X)Y@Z{GX-1)

Try it online!

Saved 2 bytes thanks to Sanchises. setdiff(...,'rows') is shorter than negating ismember(...,'rows') and it avoids one duplication. Saved another byte thanks to Luis Mendo, by switching to cells instead of arrays.

Explanation:

The MATLAB / Octave equivalents are also included.

                 % Implicitly grab input x containing cells of strings
1X)              % Get first cell. Equivalent to x{1}
   Y@            % All permutations of first row input. Equivalent to p=perms(y)
      Z{         % Convert the list of permutations to a cell array
        G        % Grab input again      
         X-      % setdiff, comparing the input cells with the permutations
           1)    % The first of the results

Input must be one the format {'abc', 'acb'}.

Stewie Griffin

Posted 2017-11-14T03:24:11.410

Reputation: 43 471

2

Pip, 11 bytes

@:_NIgFIPMa

Takes the inputs as command-line arguments. Try it online!

Explanation

          a  1st cmdline arg
        PM   List of all permutations
      FI     Filter on this function:
  _NIg         Permutation not in cmdline args
@:           First element of resulting list (with : meta-operator to lower precedence)
             Autoprint

DLosc

Posted 2017-11-14T03:24:11.410

Reputation: 21 213

2

Python 3, 87 bytes

I believe this is the only submission so far that uses neither a permutation builtin nor random shuffle/sort. Even though it's longer, I think the algorithm is pretty neat.

lambda L:[p for s in L for i,c in enumerate(s)for p in[c+s[:i]+s[i+1:]]if~-(p in L)][0]

Try it online!

Explanation

What we're doing is basically this:

def unique_anagram(string_list):
    for string in string_list:
        for i, char in enumerate(string):
            # Move the character to the beginning of the string
            permutation = char + string[:i] + string[i+1:]
            if permutation not in string_list:
                return permutation

Here's a proof that it works:

For a string S, define front(S) as the set of strings obtained by choosing one character from S and moving it to the front of S. For example, front(ABCDE) is {ABCDE, BACDE, CABDE, DABCE, EABCD}.

Now consider a list of anagrams L, such that L does not contain every possible anagram (as per the problem description). We wish to show that there exists a string S in L such that front(S) contains at least one anagram S' that is not in L.

Suppose, by way of contradiction, that for every string S in L, every string in front(S) is also in L. Observe that we can generate an arbitrary permutation of any string via a series of "fronting" moves. For example, to get

ABCDE -> BAEDC

we can do

ABCDE -> CABDE -> DCABE -> EDCAB -> AEDCB -> BAEDC

We have assumed that for each S in L, every S' in front(S) is also in L. This also means that every S'' in front(S') is in L, and so forth. Therefore, if S is in L, every permutation of S is also in L. Then L must be a complete set of anagrams, a contradiction.

So, since we are guaranteed that there is at least one permutation not in L, there must exist a string S in L for which some S' in front(S) is not in L. QED.

The code iterates over front(S) for each S in L and selects an S' which is not in L. By the above result, there will be at least one S' that qualifies.

DLosc

Posted 2017-11-14T03:24:11.410

Reputation: 21 213

2

C# (Visual C# Interactive Compiler), 116 96 bytes

s=>{for(var g="";;)if(s.All(z=>z!=(g=string.Concat(s[0].OrderBy(t=>Guid.NewGuid())))))return g;}

My golfing skills have certainly gotten better since when I first posted this!

Try it online!

Embodiment of Ignorance

Posted 2017-11-14T03:24:11.410

Reputation: 7 014

1

Husk, 6 bytes

←-⁰P←⁰

Try it online!

Mr. Xcoder

Posted 2017-11-14T03:24:11.410

Reputation: 39 774

It doesn't look like this works for inputs greater than length 2?

– MildlyMilquetoast – 2017-11-14T06:48:20.077

@MistahFiggins You can't have spaces in the array literal: https://tio.run/##yygtzv7//1HbBN1HjRsCgDSQ@v//f7RSYlKyko5SYnISkExKTlSKBQA

– Martin Ender – 2017-11-14T07:35:40.617

1

JavaScript (ES7), 172 bytes

f=(a,s=a[0],b=[...s],k=b.findIndex((e,i)=>s[i-1]>e))=>a.includes(s)?f(a,(~k?(t=b[k],b[k]=b[l=a.findIndex(e=>e>t)],b[l]=t,b.map((e,i)=>i<k?b[k+~i]:e)):b.reverse()).join``):s

Find the first lexicographic permutation of the first element of the array that's not contained in the array.

Neil

Posted 2017-11-14T03:24:11.410

Reputation: 95 035

1

Kotlin, 104 bytes

{var r=""
do{r=it[0].map{it to Math.random()}.sortedBy{(_,b)->b}.fold("",{a,(f)->a+f})}while(r in it)
r}

Beautified

{
    var r = ""
    do {
        r = it[0].map { it to Math.random() }
            .sortedBy { (_, b) -> b }
            .fold("", { a, (f) -> a + f })
    } while (r in it)
    r
}

Test

var ana: (List<String>) -> String =
{var r=""
do{r=it[0].map{it to Math.random()}.sortedBy{(_,b)->b}.fold("",{a,(f)->a+f})}while(r in it)
r}

fun main(args: Array<String>) {
    println(ana(listOf("ab")))
}

jrtapsell

Posted 2017-11-14T03:24:11.410

Reputation: 915

1

C++, 169 bytes

#import<set>
#import<string>
#import<algorithm>
using S=std::string;S f(std::set<S>l){S s=*l.begin();for(;l.count(s);)std::next_permutation(s.begin(),s.end());return s;}

Try it online!

Steadybox

Posted 2017-11-14T03:24:11.410

Reputation: 15 798

1

Scala, 50 bytes

(l:Seq[String])=>(l(0).permutations.toSet--l).head

Try it online!

Explanation

l(0)         // Take the first anagram
permutations // Built-in to get all permutations
toSet        // Convert to set, required for -- function
-- l         // Remove the original anagrams
head         // Take a random element from the set

Karl Bielefeldt

Posted 2017-11-14T03:24:11.410

Reputation: 111

1

R, 89 bytes

x=scan(,'');repeat{a=paste(sample(el(strsplit(x[1],''))),collapse='');if(!a%in%x)break};a

Repeatedly sample the letters from the first entry (as they should be anagrams of each other) and stop when one of those samples is not in the original list.

Andrew Haynes

Posted 2017-11-14T03:24:11.410

Reputation: 311

82 bytes – Giuseppe – 2017-12-11T21:28:29.807

1

PHP, 70 bytes

$j=1;while($j){$g=str_shuffle($_GET[0]);$j=in_array($g,$_GET);}echo$g;

Run on a webserver, inputting 0 indexed get values or Try it online!

Ungolfed

$j=1; //set truty value
while($j){ 
    $g=str_shuffle($_GET[0]); //shuffle the first anagram of the set
    $j=in_array($g,$_GET); //see if in the set, if false, the loop ends
}
echo $g;

SmartCoder

Posted 2017-11-14T03:24:11.410

Reputation: 131

Save two bytes with do{...}while($j); instead of $j=1;while($j){...}. Use in-place definition for $g to get rid of the braces (and save four bytes). – Titus – 2018-10-27T18:01:31.280

1

PHP, 58 55 bytes

while(in_array($s=str_shuffle($argv[1]),$argv));echo$s;

non-deterministic; takes input from command line arguments

Run with php -r <code> follwed by space separated words or try it online.

Titus

Posted 2017-11-14T03:24:11.410

Reputation: 13 814

1

Attache, 16 bytes

&\S@{!S@_[0]Ø_}

Try it online!

Explanation

&\S@{!S@_[0]Ø_}
    {         }    lambda (input: `_`)
        _[0]       first element of the given array
       @           pass to:
     !                 on each permutation:
      S                cast to string
            Ø      without any member of
             _     the input
                   this gives all anagrams not in the input
   @               then
&\S                "first string element"
&                  spread input array over each individual arguments
 \                 tale first argument
  S                as a string

Alternatives

17 bytes: {&\S! !S@_[0]Ø_}

18 bytes: {&\S! !Id@_[0]Ø_}

19 bytes: {&\S!(!Id)@_[0]Ø_}

26 bytes: {&\S!Permutations@_[0]Ø_}

26 bytes: {&\S!Permutations[_@0]Ø_}

26 bytes: {(Permutations[_@0]Ø_)@0}

26 bytes: &\S##~`Ø#Permutations@&\S

27 bytes: Last@{Permutations[_@0]Ø_}

27 bytes: `@&0@{Permutations[_@0]Ø_}

28 bytes: Last##~`Ø#Permutations@&{_}

28 bytes: Last##~`Ø#Permutations@Last

28 bytes: First@{Permutations[_@0]Ø_}

30 bytes: {NestWhile[Shuffle,`in&_,_@0]}

33 bytes: {If[(q.=Shuffle[_@0])in _,$@_,q]}

33 bytes: {q.=Shuffle[_@0]If[q in _,$@_,q]}

34 bytes: {If[Has[_,q.=Shuffle[_@0]],$@_,q]}

Conor O'Brien

Posted 2017-11-14T03:24:11.410

Reputation: 36 228

0

J, 25 bytes

((A.~i.@!@#)@{.@:>){.@-.>

The input is a list of boxed strings - I felt it was fair like this and not to declare the lists of strings explicitly as 4 8$'abcde123', 'ab3e1cd2', '321edbac', 'bcda1e23'.

I don't like the @ mess in my code, but there are a lot of serialized verbs this time.

How it works:

                         >  - unboxes the strings
 (                 )        - left verb of the fork as follows:
             @{.@:>         - unbox and take the first string
  (         )               - finds all permutations of the first string
      i.@!@#                - a list 0 .. the factorial of the length of the 1st string
   A.~                      - anagram index, all permutations
                    {.@-.   - remove the inital strings and take the first of the remaining

Try it online!

Galen Ivanov

Posted 2017-11-14T03:24:11.410

Reputation: 13 815

1

Taking input as a table, for 21 bytes: {.@(-.~i.@!@#@{.A.{.). Try it online!

– Jonah – 2017-11-15T02:30:51.017

0

05AB1E, 5 bytes

нœIмà

Try it online!

Explanation

нœIмà full program with implicit input i
н     push first element of i
 œ    push all permutations
  I   push input i
   м  remove all elements of i from the permutations
    à extract greatest element and print implicitly

Pretty much the same answer that @ThePirateBay found.

Cinari

Posted 2017-11-14T03:24:11.410

Reputation: 81

0

JavaScript, 87 bytes

a=>eval('for(s=[...a[0]];(a+[]).includes(k=s.sort(a=>~-(Math.random``*3)).join``););k')

Try it online!

This answer is based (although heavily modified) on Imme's answer. He suggested in a comment that this should be a different answer.

The problem with the old approach is because sort is completely implementation-dependent. The standard doesn't guarantee the order of calling the sort function, therefore theoretically it may never end for the first or the second test case.

This approach is few bytes longer, but it guarantee that it will finish in constrained time, even if Math.random never returns .5.

user72349

Posted 2017-11-14T03:24:11.410

Reputation:

0

CJam, 11 bytes

q~_0=m!\m0=

Try it online!

Explanation

q~  e# Read input and evaluate: ["123" "132" "231" "312" "321"]
_   e# Duplicate:               ["123" "132" "231" "312" "321"] ["123" "132" "231" "312" "321"]
0=  e# First:                   ["123" "132" "231" "312" "321"] "123"
m!  e# Permutations:            ["123" "132" "231" "312" "321"] ["123" "132" "213" "231" "312" "321"]
\   e# Swap:                    ["123" "132" "213" "231" "312" "321"] ["123" "132" "231" "312" "321"]
m0  e# Subtract, push 0:        ["213"] 0
    e# (m is used instead of - when in front of a digit)
=   e# Get item:                "213"

Esolanging Fruit

Posted 2017-11-14T03:24:11.410

Reputation: 13 542

I think there might be a typo in your explanation - The answer that your code gives is different from what your explanation says – MildlyMilquetoast – 2017-11-15T19:08:37.407

0

Perl 6, 42 bytes

{(.[0],*.comb.pick(*).join...*∉$_)[*-1]}

Try it online!

Randomly shuffles the first string of the input until it is not an element of the input.

Explanation:

{(.[0],*.comb.pick(*).join...*∉$_)[*-1]}
{                                      }   # Anonymous code block
 (                        ...    )   # Create a sequence
  .[0],   # The first element is the first element of the input
       *.comb.pick(*).join   # Each element is the previous one shuffled
                             *∉$_   # Until it is not in the input
                                  [*-1]   # Return the last element

Jo King

Posted 2017-11-14T03:24:11.410

Reputation: 38 234