Enklactify essas strings

42

Inspirado por esta cadeia de comentários ...

Quero enklactsair deste desafio, mas não posso ...

@ETHproductions para enklact (v): para implementar uma tabela de pesquisa usando uma subseção que consiste em elementos exclusivos.


Enklacting é uma maneira muito útil de compactar uma tabela de pesquisa. Por exemplo, digamos que você tenha a seguinte lista de cores:

red
green
blue
yellow
purple
orange

Se você deseja pegar uma cor como entrada e retornar seu índice nesta lista, obviamente existe a maneira mais direta:

["red", "green", "blue", "yellow", "purple", "orange"].index(input())

Mas há uma maneira de fazer isso com menos bytes:

"rgbypo".index(input()[0])

Isso funciona porque o primeiro (ou 0'th) índice de cada seqüência de caracteres é exclusivo. Este exemplo é óbvio, mas às vezes é um pouco mais difícil. E se quiséssemos criar uma tabela de pesquisa para esta lista?

Sweet Onion Chicken Teriyaki
Oven Roasted Chicken
Turkey Breast
Italian BMT
Tuna
Black Forest Ham
Meatball Marinara

Nesse caso, não podemos fazer isso:

"SOTITBM".index(input()[0])

porque existem duas entradas diferentes que começam com a 'T', a saber "Atum" e "Turquia". Devemos olhar para um índice diferente. Se você olhar para o quarto índice de cada string, notará que eles são todos únicos. Para que possamos fazer isso ...

"enklact".index(input()[3])

Nesse caso, a "cadeia de caracteres de enklaction" é "enklact".

Isso nos leva ao desafio de hoje ...

Dada uma lista de cadeias, retorne qualquer cadeia de enklaction válida. Ou, em outras palavras, dada uma lista de cadeias, retorne qualquer nova cadeia em que cada letra seja única e a cadeia seja formada juntando a i-ésima letra de cada cadeia.

Se não houver uma sequência de enklaction válida, seu envio deverá retornar uma sequência vazia ou um valor de falsy consistente. Como de costume, funções ou programas completos são permitidos e os formatos de entrada / saída são permissivos (dentro do motivo).

Cada sequência conterá apenas ASCII imprimível e esse desafio diferencia maiúsculas de minúsculas.

Isso é , então tente escrever o programa mais curto possível no seu idioma preferido!

Casos de teste

Input:
Programming
Puzzles
Code
Golf

Output (any one of these):
"ozdl"
"gzef"


Input:
the quick
brown fox
jumped over
lazy dogs

Output:
"tbjl"
"hrua"
"eomz"
" wpy"
"qne "
"if o"
"kxvs"

Note that "u dd" and "coog" are not valid.


Input:
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

Output:
""


Input:
AbC
aBc
bbC

Output:
"Aab"


Input:
@#$%^_
Hello_World
How are you?

Output:
"#eo"
"$lw"
"%l "
"^oa"


Input:
a
ab
ac

Output:
""
DJMcMayhem
fonte
Podemos retornar uma lista de strings válidas?
LyricLy
@LyricLy Hmm, agora que penso nisso, isso faria mais sentido. Mas como já existem respostas e não há muito clichê para retornar a primeira, vou dizer que não, deve haver qualquer sequência válida.
DJMcMayhem
Podemos garantir que nenhuma das strings inseridas esteja vazia?
Musicman523
6
O valor de falsy consistente pode ser um erro do tipo consistente?
Stewie Griffin
2
Com licença, mas acho que o verbo correto é enklactate .
Erik the Outgolfer

Respostas:

8

Python3, 59 bytes

lambda l:{len({*d}):''.join(d)for d in zip(*l)}.get(len(l))

Retorna uma string com o enklact, None caso contrário

PieCot
fonte
8

Python 2 , 68 67 61 bytes

lambda a:`{0:j for j in zip(*a)if len(set(j))==len(j)}`[6::5]

Experimente online!

Melhorias

  • De 68 bytes a 67 bytes por Jo King
  • De 66 a 65 bytes por Lynn

Se a saída não tivesse que ser uma sequência:

Python 3 , 49 bytes

lambda a:[j for j in zip(*a)if len({*j})==len(j)]

Experimente online!

Neil
fonte
67 bytes
Jo King
@JoKing Elegante e implementado.
519 Neil
Eu acho que max(`j`[2::5]for j in[""]+zip(*a)if len(set(j))==len(j))funciona, para salvar um byte.
Lynn
@ Lynn obrigado e atualizado.
619 Neil
7

Retina , 43 32 bytes

+/^(.).+^\1|^$/ms&m`^.

|""Lm`^.

Experimente online! Editar: salvou 11 bytes graças a @MartinEnder. Explicação:

+

Repita enquanto a entrada muda ...

/^(.).+^\1|^$/ms&

... somente se uma linha estiver vazia ou duas linhas começarem com o mesmo caractere ...

m`^.

... exclua o primeiro caractere de cada linha. Portanto, a repetição para se: a) todas as linhas começam com caracteres diferentes; nesse caso, a condição falha e a entrada não é alterada; ou b) pelo menos uma linha fica vazia; nesse caso, todos os caracteres são excluídos, Nesse ponto, a entrada para de mudar.

|""L`^.

Colete o primeiro caractere de cada linha. (Se não houver solução, o loop acima terá excluído tudo e não haverá nada para coletar.)

Neil
fonte
As opções de regex também usam modificadores de regex (gravando-os diretamente após o delimitador de fechamento): tio.run/##K0otycxLNPz/…
Martin Ender
Na verdade, isso permite que você se livre do segundo estágio inteiramente: tio.run/##K0otycxLNPz/X1s/… (de alguma forma não pode ser aplicado ma um grupo aqui, parece que o estágio condicional não propaga a opção).
Martin Ender
Ah, é claro, faça um loop condicional em vez de condicional, que resolve o erro infinito do loop na sua primeira versão. Muito arrumado!
Neil
5

Haskell , 71 bytes

f x|elem""x=""|y<-head<$>x,and[filter(==a)y==[a]|a<-y]=y|1<2=f$tail<$>x

Experimente online!

O BMO salvou 3 bytes com any null xelem""x.

Ørjan Johansen salvou um byte com sum[1|b<-y,a==b]<2filter(==a)[y]==[a].

Explicação

f x|elem""x=""                      -- Once any of the strings is empty, return "".
   |y<-head<$>x                     -- Otherwise, let y be all the first letters...
   ,and[                 |a<-y]     -- If, for all a in y,
        filter(==a)y==[a]           -- a occurs just once in y:
                               =y   -- return y.
   |1<2=f$tail<$>x                  -- Else, chop off all the first letters and recurse.

Se lançar um erro ( Prelude.head: empty list) quando não houver solução estiver OK, |elem""x=""pode ser apagado por 61 bytes .

Lynn
fonte
1
Teste mais curto:filter(==a)y==[a]
Ørjan Johansen 5/05
4

Ruby , 38 bytes

->x,*y{x.zip(*y).find{|z|z==z-[p]|[]}}

Experimente online!

Obrigado ao GB por apontar um bug.

Kirill L.
fonte
Falha se não houver correspondência e a primeira sequência não for a mais curta.
GB
@GB Você poderia dar um exemplo, por favor? Modifiquei meu último teste de acordo com a sua descrição e funcionou.
21418 Kirill L.
Tente ["abc", "ac", "acd"]
GB
Agora entendo, você está certa. Deve ser consertado.
Kirill L.
4

Pitão , 6 bytes

>1{I#C

Suíte de teste.

A saída é uma lista única, conforme permitido por padrão ; a lista [] (lista vazia, falsy) é retornada caso a sequência não possa ser enclatificada .

Explicação

> 1 {I # C - Programa completo.
     C - Transponha a entrada, cortando ausências.
    # - Filtrar por:
  {I - Invariante sob desduplicação.
> 1 - Fatia para a 1. lista [: 1] em Python.

Pitão , 5 bytes

Isso seria válido se a falha contasse como um valor falso.

h{I#C

Suíte de teste.

Mr. Xcoder
fonte
3

Haskell , 76 74 bytes

f t=last$"":(id=<<foldr(zipWith(#))([[]]<$t)t)
x#[s]=[x:s|all(/=x)s]
x#e=e

Experimente online! Retorna a última sequência de pesquisa válida ou uma sequência vazia, caso não exista.


71 69 bytes

Se lançar uma exceção consistente como valor falso, é permitido:

f t=head$id=<<foldr(zipWith(#))([[]]<$t)t
x#[s]=[x:s|all(/=x)s]
x#e=e

Experimente online! Lança uma empty listexceção se nenhuma string for encontrada, retorna a primeira string válida caso contrário.

-2 bytes graças a Ørjan Johansen

Laikoni
fonte
1
notElem x pode ser reduzido para all(/=x).
Ørjan Johansen
2

Geléia , 7 bytes

z0Q€fZḢ

Retorna o número inteiro 0 se as seqüências não puderem ser enklactificadas.

Experimente online!

Como funciona

z0Q€fZḢ  Main link. Argument: A (string array)

z0       Zip/transpose, filling shorter rows with 0.
  Q€     Unique each deduplicate resulting string.
     Z   Zip/transpose, without using a filler.
    f    Filter; keep only string that appear in the results to both sides.
      Ḣ  Head; extract the first string. Returns 0 if the array is empty.
Dennis
fonte
2

Stax , 9 8 bytes

åτIⁿs↓µg

Execute e depure

Explicação (sem embalagem):

M{c0-u=}j Full program, implicit input
          e.g. ["Programming", "Puzzles", "Code", "Golf"]
M         Transpose
                ["PPCG", "ruoo", "ozdl", "gzef", "rl\0\0", "ae\0\0", "ms\0\0", "m\0\0\0", "i\0\0\0", "n\0\0\0", "g\0\0\0"]
 {     }j Find first matching element:
            e.g. "PPCG"
  c0-       Copy and remove zero bytes (padding)
                 "PPCG" "PPCG"
     u      Unique
                 "PPCG" "PCG"
      =     Check if equal:
                 1
          First matching here: "ozdl". If none is found, the stack is empty
          Implicit output if anything on stack
wastl
fonte
2

R , 127 bytes

function(S,s=sapply(S,substring,x<-1:max(nchar(S)+1),x))cat(rbind(s[!apply(s,1,anyDuplicated)&!rowSums(s==""),],"")[1,],sep="")

Experimente online!

sapplynormalmente retorna a matrixquando todos length(FUN(X[[i]]))são iguais, exceto quando length(FUN(X[[i]]))==1, nesse caso, retorna a vector. Para usar as operações da matriz, precisamos de substringmais uma do que precisamos para garantir a matrix, razão pela qual ela xse estende max(nchar(S)+1).

Em seguida, filtramos as linhas que não têm duplicatas nem seqüências de caracteres vazias. Como só podemos retornar uma única string, pegamos a primeira, exceto que, quando não houver linhas que atendam aos critérios, lançaríamos um erro; portanto, acrescentamos uma linha extra ""ao final.

Em seguida, imprimimos a enklactstring ified ou a string vazia.

Giuseppe
fonte
2

R , 116 107 95 bytes

R + pryr

pryr::f(for(i in 1:min(nchar(v)))`if`(anyDuplicated(t<-substr(v,i,i)),0,{cat(t,sep="")
break}))

Experimente online!

base R

function(v)for(i in 1:min(nchar(v)))`if`(anyDuplicated(t<-substr(v,i,i)),0,{cat(t,sep="")
v=0})

Experimente online!

Essas duas variantes economizam 9 bytes graças a Giuseppe .

Explicação:

Isso efetivamente trunca todas as picadas do vetor vno comprimento mais curto e itera pelos índices subsequentes. Em seguida, verifica se há duplicatas nas letras escolhidas e, se não, as cola e as imprime cat. Se todos os índices retornarem resultados duplicados, isso imprimirá uma sequência vazia.
Todos agrupados em uma pryrfunção anônima com breakpara interromper o loop ou a função R básica zera o vetor para interromper o loop.

pajonk
fonte
1
Agradável! Isto pode ser golfed para 107 bytes em R+pryrou 107 bytes em base de R.
Giuseppe
2

Japonês, 9 bytes

Recebe a entrada como uma matriz de matrizes de caracteres, retorna uma matriz de caracteres ou undefined

y æ_f eZâ

Experimente (adicione uma nova linha no início do programa com o código qR mqpara receber a entrada como uma sequência separada de nova linha, para economizar o trabalho de criar as matrizes.)


Explicação

y             :Transpose
  æ_          :Pass each array Z through a function and return the first that returns true
    f         :  Filter nulls (used for padding when transposing)
      e       :  Test for equality with
       Zâ     :  Z deduplicated
Shaggy
fonte
Eu tentei o desafio antes de ler sua solução e obtive uma solução quase idêntica:z æ_¬eZ¬â
Nit 05/05
Exatamente idêntico, exceto o formato de entrada.
Shaggy
2

05AB1E , 7 bytes

øʒDÙQ}н

Experimente online!

Explicação

ø        # Zip the input array
 ʒ   }   # Filter by ...
  DÙQ    # ... an entry is equal to itself deduplicated
      н  # Take the first element
Kaldo
fonte
1

Python 3 , 75 bytes

def f(t):c=[s.pop(0)for s in t];return all(t)and(f(t),c)[len(t)==len({*c})]

Opera em listas de caracteres em vez de cadeias. Retorna False se não houver uma sequência de enklaction válida.

Experimente online!

musicman523
fonte
Eu acho que isso se repete, o que tornaria inválido, a menos que f=esteja incluído na contagem de bytes.
LyricLy
@LyricLy Fixed :)
musicman523
1

C (gcc) , 161 bytes

f(s,i)char**s;{char**t,a[255],*u=a;for(i=0;memset(a,0,255),u&&~i;i+=!!~i&&u)for(t=s;(u=u?*t++:0)&&~(i=u[i]?i:-1)&&!a[u[i]]++;);while(~i&&(u=*s++))putchar(u[i]);}

Experimente online!

Cada posição de caractere é testada para duplicação e pulada se uma duplicata for detectada; isso continua até que a corda mais curta termine. Infelizmente, é apenas ASCII: seqüências de caracteres DBCS / UTF-8 quebram muito essa função!

ErikF
fonte
152 bytes
ceilingcat
1

Japonês , 12 bytes

Retorna undefinedpara cadeias não enklactic.

y ·æ_¬n ä¦ e

Experimente online!

Explicação:

y ·æ_¬n ä¦ e
y             // Split the input at newlines and transpose
  ·           // Join on newlines 
   æ_         // Return the first item that returns truthy when ran through:
     ¬n       //   Sort
        ä¦    //   Reduce with !=
           e  //   All items are truthy (unique)
Oliver
fonte
Você deve poder salvar 2 bytes usando a entrada como uma matriz de matrizes de caracteres e abandonando os dois splits.
Shaggy
1

Wolfram Language (Mathematica) , 54 bytes

#&@@Select[PadRight@#,#~FreeQ~0&&Union@#==Sort@#&]&

Experimente online!

Pega uma lista da lista de caracteres como entrada, retorna uma lista de caracteres. Contém U + F3C7, correspondente ao operador "Transpose".

Retorna #1e gera um monte de erros ignoráveis ​​quando não há uma string adequada.

Explicação:

PadRight@#

Coloque a entrada de forma que cada "sequência" (lista de caracteres) tenha o mesmo comprimento. Isso acrescenta o número inteiro 0s (não a sequência "0"s). Então transponha.

Select[ ... ,#~FreeQ~0&&Union@#==Sort@#&]

Selecione as strings que não possuem um número inteiro 0s e possuem todos os caracteres exclusivos.

#&@@

Pegue o primeiro.

JungHwan Min
fonte
1

JavaScript (ES6), 66 bytes

Retorna uma string ou undefinedse não existe solução.

f=(a,i=0)=>a.every(s=>(o[k+=c=s[i],c]^=1)&&c,o=k=[])?k:c&&f(a,i+1)

Experimente online!

Comentado

f = (           // f = recursive function taking:
  a,            //   a[] = input array
  i = 0         //   i   = pointer
) =>            //
  a.every(s =>  // for each string s in a[]:
    (o[k +=     //   append to the key string k
      c = s[i], //   the character c at position i in s
      c] ^= 1   //   and toggle o[c] (undefined -> 1 -> 0)
    ) && c,     //   additionally, make sure that c is defined
    o = k = []  //   start with o = k = empty array
  ) ?           // every() is true if all characters were distinct and defined:
    k           //   in which case we return k
  :             // else:
    c &&        //   provided that every() didn't fail because of an undefined character,
    f(a, i + 1) //   try again at the next position
Arnauld
fonte
1

Carvão , 23 21 bytes

-2 bytes graças a @Neil !

§ΦE⌊EθLι⭆θ§λι⬤ι⁼¹№ιλ⁰

Experimente online!

Somente ASCII
fonte
Ah, quando a) qdeixou de ser sempre uma string b) O StringMap começou a trabalhar em não-strings? De qualquer forma, você Rangeé desnecessário, economizando 2 bytes.
Neil
@ Nee a) Quando adicionei entrada de matriz / objeto b)> _> Não tenho certeza. provavelmente por volta do tempo em que eu fixo o loop while (desculpe, esqueci de mencionar um desses)
ASCII-only
1

Casca , 9 bytes

ḟS=UḞz:∞ø

Experimente online!

Explicação

fS=UḞz:∞ø
    Ḟz:∞ø  Transpose the input dropping characters of longer strings
    Ḟ        Fold right
     z:      Zip with prepend
       ∞ø    Infinite list of empty lists
ḟS=U       Find the first string without duplicates, returns an empty string if none
ḟ            Return first value satisfying predicate
  =          Equal
 S U         to itself with duplicates removed
Fyr
fonte
Usar ←ġLTover Ḟz:∞ødeve salvar um byte.
ბიმო
1

Retina , 81 56 bytes

m`$
$.=*£¢
N$`.
$.%`
¶

~`(.*?¢)+
L`.{$#1}
A`(.).*\1|£|¢

Experimente online!

-25 bytes graças a @Neil


Transpor texto retangular na Retina é surpreendentemente difícil.

TwiNight
fonte
Eu gostaria de conhecer uma maneira melhor de realizar a transposição retangular, mas nesse meio tempo, economize 25 bytes .
719 Neil
@ Neil Ahh ... estágio eval. Eu sempre esqueço retina 1.0 tem todas essas frias novos recursos
TwiNight
1

Perl 6 , 27 bytes

{([Z] $_).first:{.Set==$_}}

Experimente online!

Depois de ver que a versão ruby ​​foi votada, copiei a abordagem e usei listas de caracteres, em vez de strings. Eu não gosto disso

Meu envio mais antigo e mais correto é o seguinte:

Perl 6 , 38 bytes

Divida, feche, verifique a exclusividade, entre.

{[~] ([Z] @_>>.comb).first:{.Set==$_}}

Experimente online!

Jarrod Funnell
fonte
1

C (gcc) , 121 113 110 bytes

i;d;f(s)char**s;{char**_=s,x[255]={0},y[99]={0};for(d=i=0;*_;)d+=x[y[i++]=*(*_++)++]++;d=d?*x?0:f(s):puts(y);}

Experimente online!

Ungolfed

void enklactify(char *strings[]) {
    int quit = 0;
    while (!quit) {
        char **arg = strings;      // current row
        int exists[255] = {0};     // which characters exist in the column
        char output[99] = {0};     // will hold output string
        int index = 0;             // where to insert in output
        int duplicates = 0;        // have we found any duplicates?
        while (*arg != NULL) {
            char *word = *arg;     // current word
            char first = *word;    // first letter of current word
            if (exists[first])
                duplicates = 1;    // we found a duplicate
            exists[first] = 1;     // mark it as in our string
            output[index] = first; // add it to our output
            index++;
            (*arg)++;              // advances the current word to the next
                                   // character by reference (chops first char)
            arg++;                 // advance to next whole argument
        }

        if (!duplicates) {         // This is a valid solution
            puts(output);
            quit = 1;
        }

        if (exists[0]) {           // We hit the null terminator of one of the
                                   // input strings, so we failed
            quit = 1;
        }
    }
}

-3 graças a ceilingcat

Isso abusa da capacidade de adicionar apenas 1 a um ponteiro de string em C para obter o 'rabo' da string. Os principais economizadores de bytes são:

  • d+=x[y[i++]=*(*_)++]++que acrescenta o primeiro caractere da primeira sequência de _a y, avança a primeira sequência de _para remover seu primeiro caractere, adiciona a xentrada nesse caractere a de incrementa a referida xentrada
  • q=d?*x:puts(y)que imprime yse dfor diferente de zero ao definir qum valor diferente de zero ou define qcomo diferente de zero se o primeiro elemento de xfor diferente de zero (se estivéssemos no final de uma das cadeias de caracteres, o referido elemento seria diferente de zero zero)

Editar: bytes raspados alternando do loop while para a chamada de recursividade e removendo os colchetes do loop for.

LambdaBeta
fonte
Sugerir em for(d=i=0;*_;)vez de for(d=0,i=0;*_;++_)e em *(*_++)++]++;d=d?!*x*f(s)vez de*(*_)++]++;d=d?*x?0:f(s)
tetocat 21/06
0

Pitão, 13 bytes

e+kf{[email protected]

Experimente aqui

e+kf{[email protected]
           .tQ   Transpose the (implicit) input with padding.
        .TQ      Transpose the input without padding.
       @         Take the strings in both.
   f{IT          Find the ones that have no duplicates.
e+k              Get the last, or an empty string.
Mnemônico
fonte
1
Parece que retornar uma lista de todas as seqüências válidas não é válido.
LyricLy
@LyricLy Fixed.
Mnemônico
0

Vermelho , 139 bytes

func[b][m: length? first b foreach a b[m: min m length? a]repeat n m[c: copy[]foreach a b[append c a/(n)]if c = unique c[return rejoin c]]]

Experimente online!

Explicação:

Toma a entrada como um bloco (lista) de strings. Retorna a sequência de enklaction ou noneoutra.

f: func[b][
    m: length? first b                   ; the minimal length of the first string  
    foreach a b[m: min m length? a]      ; find the minimal length of all strings
    repeat n m[                          ; limit the search to the minimal length
        c: copy[]                        ; an empty block  
        foreach a b[append c a/(n)]      ; for each string append the current char
        if c = unique c[return rejoin c] ; if all chars are unique, return the block
    ]  
]
Galen Ivanov
fonte
0

Röda , 80 77 bytes

f a{a|seq 0,#_|try{{|i|a|[_[i:i+1]]|orderedUniq|concat|[_]if[#_1=#a]}_|head}}

Experimente online!

-1 byte graças ao vacas charlatão

Explicação:

f a{
  a|         /* Push the strings in a to the stream */
             /* For each string (_): */
  seq 0,#_|     /* Push a range from 0 to the length of _ to the stream */
  try{       /* Ignore errors during the following block */
    {|i|        /* For each i in the stream: */
      a|           /* Push strings in a to the stream */
      [_[i:i+1]]|  /* For each string, push the ith character to the stream */
      orderedUniq| /* Remove duplicate characters */
      concat|      /* Join the characters into a string */
      [_]if        /* Push the string to the stream if */
      [#_1=#a]     /* Its length is the length of a */
    }_|
    head        /* Take the first string in the stream and return it */
  }
}

A trypalavra-chave é usada para descartar erros que ocorrem se ifor maior que o comprimento da menor string aou se não houver resposta e headcausar um erro.

fergusq
fonte
Você pode remover as parênteses seqpara salvar um byte
Kritixi Lithos 5/05
@Cowsquack Thanks!
Fergusq # 5/18
0

Java 10, 106 bytes

a->{for(int i=0;;i++){var r="";for(var s:a)r+=s[i];if(r.length()==r.chars().distinct().count())return r;}}

Irá gerar um erro em vez de retornar uma String vazia se nenhuma solução puder ser encontrada. Entrada é uma matriz de caracteres.

Experimente online.

Explicação:

a->{                  // Method with character-matrix parameter and String return-type
  for(int i=0;;i++){  //  Loop `i` upwards
    var r="";         //   Result-String, starting empty
    for(var s:a)      //   Loop over the character-arrays of the input
      r+=s[i];        //    And append every `i`'th character to `r`
    if(r.length()==r.chars().distinct().count())
                      //   If `r` only contains unique characters
      return r;}}     //    Return `r` as result
Kevin Cruijssen
fonte
O OP não parecia querer permitir erros, embora nunca o tenha colocado no próprio post.
Ørjan Johansen
0

Clojure, 59 bytes

#(for[s(apply map list %):when(=(count(set s))(count %))]s)

Retorna uma lista de listas de caracteres.

NikoNyrh
fonte
0

APL + WIN, 35 33 bytes

2 bytes salvos graças a Adám

Solicita as linhas de texto como uma matriz de caracteres:

⊃((↑⍴¨a)=+/¨((a⍳¨a)=⍳¨⍴¨a))/a←,⌿⎕

Experimente online! Cortesia de Dyalog Classic

Explicação:

a←,⌿⎕ prompts for input and creates a nested vector of the input matrix columns

((a⍳¨a)=⍳¨⍴¨a) creates a binary vector for each nested element with a 1 for each unique element

((↑⍴¨a)=+/¨ sums each binary vector and compares to number of characters in each element

(...)/a←⊂[1]⎕ selects only those elements where number of uniques = column length

⊃ converts nested vector back to a matrix of each valid enklaction string 
Graham
fonte