Converter n sequências de comprimento m em m sequências de comprimento n


16

Escreva um programa que, dado qualquer número 'n' de strings de 'm' de comprimento, retorne 'm' número de strings de 'n' de comprimento, com esta condição:

Cada nova string deve conter as letras no mesmo índice das outras strings

Por exemplo, a primeira cadeia de saída deve conter a primeira letra de todas as cadeias de entrada, a segunda cadeia de saída deve conter a segunda letra de todas as cadeias de entrada e assim por diante.

Exemplos (os números sob as letras são os índices das strings):

input: "car", "dog", "man", "yay"
        012    012    012    012
output: "cdmy", "aoaa", "rgny"
         0000    1111    2222

input: "money", "taken", "trust"
        01234    01234    01234
output: "mtt", "oar", "nku", "ees", "ynt"
         000    111    222    333    444

Suponha que a entrada esteja correta sempre

O código dos bytes mais curtos vence!

Editar:

Como existem muitas linguagens de programação e pode haver muitas soluções possíveis para cada uma delas, publicarei a solução mais curta para cada linguagem de programação e para o usuário que a forneceu. Continue codificando!

Reeditar:

Graças ao usuário Dennis , inseri um trecho para as tabelas de classificação.


2
Temos um snippet de cabeçalho que você pode adicionar ao seu corpo de pergunta. Não há necessidade de fazer isso manualmente.
Dennis


Me desculpe, eu não sabia que era chamado de "transposição"
Input Name Here

6
Não acredito que esses desafios sejam duplicados, devido às diferenças que envolvem transposição irregular e algum tratamento estranho de espaço em branco na outra questão. Embora em algumas línguas as respostas sejam muito semelhantes, acho que na maioria elas serão diferentes o suficiente para que isso não deva ser uma duplicata.
FryAmTheEggman

Respostas:



9

Python, 36 29 bytes

zip(*s) retorna uma lista de tuplas de cada caractere, transpostas.

lambda s:map(''.join,zip(*s))

Experimente online


A saída diz "cdmy", "aoaa", "rgny", que é uma lista ["cdmy", "aoaa", "rgny"]ou uma tupla("cdmy", "aoaa", "rgny")
mbomb007

map(''.join,zip(*s))também trabalha para a conversão string (Python apenas 2), e para Python 3, [*map(''.join,zip(*s))]afaik funciona
Valor de tinta

@ KevinLau-notKenny também map(''.join,zip(*s))é válido para Python 3 - por padrão, permitimos iteradores / geradores no lugar de listas.
Mego



7

PowerShell v2 +, 66 54 bytes

param($n)for($x=0;$n[0][$x];$x++){-join($n|%{$_[$x]})}

Ei ... não map, não zip, não transpose, etc., então começamos a rolar. Grandes adereços para @DarthTwon para o golfe de 12 bytes.

Recebe entrada $n, configura um forloop. A inicialização é definida $xcomo 0, o teste é se ainda temos letras em nossa palavra $n[0][$x]e incrementamos $x++cada iteração.

Dentro do loop, pegamos nossa matriz de strings e o canalizamos para um loop interno que cospe o caractere apropriado de cada palavra. Isso é encapsulado em a -joinpara formar uma sequência e essa sequência é deixada no pipeline. No final da execução, as seqüências de caracteres no pipeline são implicitamente impressas.

PS C:\Tools\Scripts\golfing> .\convert-n-strings.ps1 "Darth","-Twon","Rocks"
D-R
aTo
rwc
tok
hns

1
Bom, esse é o tipo de resposta que eu queria ver;) É uma escrita muito simples, em ,vez de pensar na resposta
Input Name Here

Usando um loop while pode pare ainda que abaixo: param($n)$x=0;while($n[0][$x]){-join($n|%{$_[$x]});$x++}. E não há erros aqui: D
ThePoShWolf

@DarthTwon Excellent. Ou use um forloop para outros dois. ;-)
AdmBorkBork

Hmm ... eu tentei isso, mas não depois de realmente reduzir meu whileciclo. Bom trabalho, senhor!
ThePoShWolf

Você pode usar o Linq no Powershell?
aloisdg movendo-se para codidact.com

7

Vim, 37 36 pressionamentos de tecla

Todas as outras respostas são monótonas e usam componentes monótonos de um byte. Aqui está uma resposta hacky que faz a coisa toda manualmente, em algo que nem sequer é uma linguagem de programação:

Gmaqqgg:s/./&<cr>d<C-v>`aGo<esc>pvGgJ@qq@q`adgg

Explicação:

G                                   "move to the end of this line
     ma                             "And leave mark 'a' here
       qq                           "Start recording in register 'q'
         gg                         "Move to the beginning
           :s/./&<cr>               "Assert that there is atleast one character on this line
                      d             "Delete
                       <C-v>        "Blockwise
                            `a      "Until mark 'a'

    G                               "Move to the end of the buffer
     o<esc>                         "Open a newline below us
           p                        "And paste what we deleted
            vG                      "Visually select everything until the end
              gJ                    "And join these without spaces
                @q                  "Call macro 'q'. The first time, this will do nothing,
                                    "The second time, it will cause recursion.
                  q                 "Stop recording
                   @q               "Call macro 'q' to start it all

Agora, está tudo bem, mas o buffer tem algum texto extra sobrando. Então devemos:

`a                              "Move to mark 'a'
  dgg                           "And delete everything until the first line



4

Retina , 45 43 bytes

A contagem de bytes assume a codificação ISO 8859-1.

O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+

O avanço de linha principal é significativo. Entrada e saída são listas terminadas com avanço de linha de seqüências de caracteres ASCII imprimíveis (observe que ambos têm um único avanço de linha final).

Experimente online!

Eu sabia por um tempo que a transposição de blocos retangulares seria uma dor na Retina (enquanto a transposição de quadrados não é tão ruim), mas nunca realmente tentei. A primeira solução foi de fato de 110 bytes, mas após várias mudanças substanciais na abordagem, os 45 bytes resultantes não são tão ruins quanto eu suspeitava (mas ainda assim ...). A explicação seguirá amanhã.

Explicação

Etapa 1: Classificar

O$#`.(?<=(.+))|¶
$.1

Isso faz o trabalho principal de reordenar os caracteres na entrada, mas acaba atrapalhando a separação em linhas. Curiosamente, se removermos o , obteremos o código necessário para transpor uma entrada quadrada.

Os estágios de classificação (indicados por O) funcionam assim: eles encontram todas as correspondências da regex especificada (a coisa após a `) e, em seguida, classificam essas correspondências e as reinserem nos locais onde as correspondências foram encontradas. Por acaso, esse regex corresponde a todos os caracteres: feeds sem linha via .(?<=(.*))alternativa e feeds de linha via . Portanto, ele classifica todos os caracteres na entrada. A parte mais interessante é o que são classificados por .

A $opção ativa um modo "ordenar por", em que cada partida é substituída pelo padrão de substituição na segunda linha, que é usada para comparar as partidas. Além disso, o# informa ao Retina para converter o resultado da substituição em um número inteiro e comparar esses números inteiros (em vez de tratá-los como seqüências de caracteres).

Então, finalmente, precisamos olhar para o regex e a substituição. Se a primeira alternativa corresponder (ou seja, correspondermos a qualquer caractere dentro de uma das linhas), o grupo (?<=(.*))capturará tudo até esse caractere nessa linha no grupo 1. O $.1padrão de substituição substitui isso pelo comprimento do grupo 1. Portanto, o primeiro caractere em cada string se torna 1, o segundo se torna 2, o terceiro se torna3 e assim por diante. Agora deve ficar claro como isso transpõe uma entrada quadrada: todos os primeiros caracteres das linhas vêm primeiro e todos acabam na linha superior, depois todos os segundos caracteres terminam na segunda linha e assim por diante. Mas para essas entradas retangulares, também estamos combinando os feeds de linha. Desde grupo1não é usado nesse caso, a substituição está vazia, mas para os fins da #opção, isso é considerado 0. Isso significa que todos os feeds de linha são classificados para a frente.

Portanto, agora temos os caracteres na primeira ordem (primeiro caractere de cada string, segundo caractere de cada string, etc.) e todos os feeds de linha no início.

Etapa 2: partida

!`(?<=(¶)+.*)(?<-1>.)+

Agora precisamos dividir os caracteres em linhas do tamanho correto. Esse comprimento corresponde ao número de linhas na entrada original, que corresponde ao número de feeds de linha que temos no início da string.

A divisão é feita aqui com a ajuda de um estágio de correspondência, que simplesmente encontra todas as correspondências do regex especificado e usa a !opção para imprimir essas correspondências (o padrão seria contá-las). Portanto, o objetivo da regex é corresponder uma linha por vez.

Começamos "contando" o número com o lookback atrás (?<=(¶)*.*). Ele gera uma captura em grupo 1para cada avanço de linha na frente.

Então, para cada uma dessas capturas, combinamos um único caractere com (?<-1>.)+.


4

código de máquina x86, 19 bytes

Em hexadecimal:

fc89d35651a401dee2fb91aa595e464a75f1c3

Entrada:: ECX# de strings (n) EDX,: comprimento individual de strings (m) ESI,: array de strings de entrada,: EDIbuffer de saída que recebe o array de strings. Presume-se que a matriz seja definida como char src[n][m+1]para entrada e char dst[m][n+1]saída, e todas as seqüências são terminadas em NULL.

0:  fc                  cld
1:  89 d3               mov ebx,edx   ;EDX is the counter for the outer loop
_outer:
3:  56                  push esi
4:  51                  push ecx
_inner:
5:  a4                  movsb         ;[EDI++]=[ESI++]
6:  01 de               add esi,ebx   ;Same char, next string
8:  e2 fb               loop _inner   ;--ECX==0 => break
a:  91                  xchg eax,ecx  ;EAX=0
b:  aa                  stosb         ;NULL-terminate just completed string
c:  59                  pop ecx
d:  5e                  pop esi       ;First string,
e:  46                  inc esi       ;...next char
f:  4a                  dec edx
10: 75 f1               jnz _outer
12: c3                  ret

3

Braquilog , 5 bytes

z:ca.

Espera uma lista de strings como entrada, por exemplo run_from_atom('z:ca.',["money":"taken":"trust"],Output).

Explicação

z       Zip the strings in the Input list
 :ca.   output is the application of concatenation to each element of the zip

3

05AB1E, 3 bytes

ø€J

Explicado

     # implicit input, eg: ['car', 'dog', 'man', 'yay']
ø    # zip, producing [['c', 'd', 'm', 'y'], ['a', 'o', 'a', 'a'], ['r', 'g', 'n', 'y']]
 €J  # map join, resulting in ['cdmy', 'aoaa', 'rgny']

Experimente online



2

JavaScript ES6, 48 46 bytes

a=>[...a[0]].map((n,x)=>a.map(a=>a[x]).join``)

Sinto-me deixado de fora, não temos nenhuma função zip integrada. Obrigado nicael por apontar meu erro de tipo.

Uso

(a=>[...a[0]].map((n,x)=>a.map(a=>a[x])))(["asd","dsa"]); //or whatever is above, might change due to edits

retorna

["ad","ss","da"]

Exceção: TypeError: a [0] .map não é uma função
edc65 12/12/16

1
Você precisa [...a[0]].map, já que a[0]não é uma matriz.
Nicael 12/07

@nicael thanks. estragou os tipos. isso prova por que eu não deveria jogar golfe tão cedo.
Charredgrass

@nicael Editei- .joinos para resolver esse problema.
Charredgrass

1
join`` em vez de join('')salvar 2 bytes. Downvote retraído
edc65

2

Utilitários Bash + BSD, 27

sed s/./\&:/g|rs -c: -g0 -T

E / S via cadeias separadas por nova linha STDIN / STDOUT.

Pode ser necessário instalar rscom sudo apt install rsou similar. Funciona imediatamente no OS X.

A -Topção de rsfazer o trabalho pesado da transposição. O resto é apenas formatação:

  • O sedcomando simplesmente insere :após cada caractere
  • -c:especifica que as colunas de entrada são :separadas
  • -g0 especifica que as colunas de saída têm separação de largura zero

Se minha leitura da página de rsmanual estiver correta, o seguinte deverá funcionar com uma pontuação de 12, mas infelizmente não funciona - veja a nota abaixo:

rs -E -g0 -T

Exemplo de saída:

$ printf "%s\n" car dog man yay |sed s/./\&:/g|rs -c: -g0 -T
cdmy
aoaa
rgny
$

Se se espera que a entrada seja toda ASCII imprimível, ela :pode ser substituída por algum caractere não imprimível, por exemplo, 0x7 BEL.


Nota

Queria entender por que não consegui -Etrabalhar com a opção e me livrar do sedpré - processamento. Encontrei o rscódigo fonte aqui . Como você pode ver, dar essa opção define o ONEPERCHARsinalizador. No entanto, não há nada no código que realmente verifique o estado desse sinalizador. Então, acho que podemos dizer que, apesar do fato de essa opção estar documentada, ela não é implementada.

De fato, esta opção está documentada na página de rsmanual do Linux :

-E Considere cada caractere de entrada como uma entrada de matriz.

mas não a versão do OS X.


2

PHP, 82 bytes

function f($a){foreach($a as$s)foreach(str_split($s)as$i=>$c)$y[$i].=$c;return$y;}

pega e retorna uma matriz de strings

demolir

function f($a)
{
    foreach($a as$s)                    // loop through array $a
        foreach(str_split($s)as$i=>$c)  // split string to array, loop through characters
            $y[$i].=$c;                 // append character to $i-th result string
    return$y;
}

exemplos

$samples=[
    ["asd","dsa"], ["ad","ss","da"],
    ["car", "dog", "man", "yay"], ["cdmy", "aoaa", "rgny"],
    ["money", "taken", "trust"], ["mtt", "oar", "nku", "ees", "ynt"]
];
echo '<pre>';
while ($samples)
{
    echo '<b>in:</b> ';         print_r($x=array_shift($samples));
    echo '<b>out:</b> ';        print_r(f($x));
    echo '<b>expected:</b> ';   print_r(array_shift($samples));
    echo '<hr>';
}

2

APL, 3 bytes

↓⍉↑

pega as seqüências de entrada e as transforma em uma matriz de caracteres. transpõe a matriz. divide novamente as linhas da matriz resultante em seqüências de caracteres.



1

Mathematica, 26 bytes

""<>#&/@(Characters@#)&

Função anônima. Pega uma lista de cadeias como entrada e retorna uma lista de cadeias como saída. O caractere Unicode é U + F3C7, representando \[Transpose]. Trabalha convertendo para uma matriz de caracteres, transpondo e convertendo de volta para uma lista de cadeias. Se o formato de entrada / saída for esticado, uma simples transposição de 5 bytes funcionará:

#&

+1 você me venceu! (Mas não consegui usar o símbolo Transpose.) A propósito, por que o T não aparece na tela? (Está lá quando eu copio seu código no Mathematica).
21416

@DavidC O caractere Unicode está na Área de Uso Privado, que é marcada como uma seção para caracteres proprietários e, portanto, não é oficialmente atribuído um glifo nem renderizado na maioria das fontes. A fonte do Mathematica passa a renderizar esse caractere como um T com subescrito e interpretá-lo como um \[Transpose].
LegionMammal978

@DavidC Por que eles não usam ?
Adám

@ Adám IDK, você teria que perguntar a Wolfram Research sobre isso, não me
LegionMammal978

@ LegionMammal978 Não, eu estou feliz contanto que eu tenha o óbvio da APL .
Adám

1

MATLAB / oitava, 4 bytes

@(x)x'

Isso define uma função anônima. O formato de entrada é ['car'; 'dog'; 'man'; 'yay'].

Experimente aqui .


Qual formato é a entrada para esta solução? Eu não acho que ele vai trabalhar com a forma como Matlab processa cadeias se você tentar introduzir-los de uma forma Matlabby, por exemplo f = @(x)x', f([{'abcd'},{'abcd'},{'abcd'}])saídas ans = 'abcd' 'abcd' 'ABCD'
sintaxe

O formato de entrada @sintax deve ser uma matriz de caracteres 2D, como no exemplo vinculado na resposta. Você está usando uma matriz de células de seqüências de caracteres (obtida concatenando matrizes de células singleton). Ele deve ser: f(['abcd';'abcd';'abcd']). Eu editei a resposta para especificar o formato de entrada
Luis Mendo

1

Haskell, 41 bytes

f l=zipWith($)[map(!!n)|n<-[0..]]$l<$l!!0

Ou com um pouco mais de ar:

f l = zipWith ($) [map (!! n) | n <- [0..]] $
                  l <$ (l !! 0)

A segunda lista é a lista de palavras repetidas "o comprimento de uma palavra". Em cada lista de palavras, selecionamos a n-ésima letra de cada palavra, fornecendo o resultado.


1
Não há necessidade de um programa completo, porque "programa" significa "programa ou função" ; portanto, uma função é suficiente. Você pode passar e retornar uma lista de strings e, portanto, omitir wordse unwords. Além disso, map(\_->l)(l!!0)é l<*l!!0, então tudo se resume a \l->zipWith($)[map(!!n)|n<-[0..]]$l<$l!!0.
nimi

Oh, bom obrigado :) Estou atualizando.
villou24

Opa, erro de digitação: está l<$l!!0(primeira vez errada, segunda vez certa), mas você acertou mesmo assim.
nimi

1

Lisp comum, 62 bytes

(lambda(s)(apply'map'list(lambda(&rest x)(coerce x'string))s))

A mapfunção usa um tipo de resultado (aqui list), uma função f para aplicar e uma ou mais seqüências s1 , ..., sn . Todas as sequências são iteradas em paralelo. Para cada tupla de elementos (e1, ..., en) extraídos dessas seqüências, chamamos (f e1 ... en) e o resultado é acumulado em uma sequência do tipo desejado.

Pegamos uma lista de strings, digamos ("car" "dog" "man" "yay"), e usamos applypara ligar map. Temos que fazer isso para que a lista de entrada seja usada como mais argumentos para map. Mais precisamente, isso:

(apply #'map 'list fn '("car" "dog" "man" "yay"))

... é equivalente a:

(map 'list f "car" "dog" "man" "yay")

E como strings são seqüências, iteramos em paralelo sobre todos os primeiros caracteres, depois todos os segundos caracteres, etc ... Por exemplo, a primeira iteração chama f da seguinte maneira:

(f #\c #\d #\m #\y)

O lambda anônimo pega a lista de argumentos dados e a força a voltar a uma string.



0

Ruby, 46 bytes

Provavelmente, a primeira vez que "strings de Ruby não são enumeráveis" está realmente me mordendo muito, pois tive que mapear as strings em matrizes antes do processamento. (Normalmente, a necessidade de usar String#charsnão é suficiente para a perda de bytes, mas como eu preciso mapeá-los, isso dói muito mais)

->s{s.map!(&:chars).shift.zip(*s).map &:join}

0

Clojure, 68 bytes

#(map(fn[g](reduce(fn[a b](str a(nth b g)))""%))(range(count(% 0))))

Mapeia uma função que é apenas reduce (vai nos elementos da lista um por um e une o enésimo caractere da sequência) no intervalo de 0 a comprimento da primeira sequência.

Veja on-line: https://ideone.com/pwhZ8e


0

C #, 53 bytes

t=>t[0].Select((_,i)=>t.Aggregate("",(a,b)=>a+b[i]));

C # lambda ( Func) onde a saída é IList<string>e a saída é IEnumerable<string>. Não sei como funciona zipem outro idioma, mas não consigo encontrar uma maneira de usar o c # aqui. Aggregateatender bem a necessidade. Não há transposição em C #, existe uma no Excel, mas eu não a utilizarei.

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.