Esteganografia com letra dobrada


19

A esteganografia oculta uma mensagem dentro de uma transportadora, produzindo um pacote que não parece suspeito. Para esse desafio, você escreverá um programa que recebe uma mensagem ASCII e uma transportadora ASCII como entrada e retornará ou imprimirá um pacote idêntico à transportadora, exceto que os caracteres correspondentes à mensagem serão duplicados, na mesma ordem em que aparecem em a mensagem.

Regras:

  1. Se a transportadora já contiver seqüências do mesmo caractere mais de uma vez e não forem usadas para codificar um caractere da mensagem, o programa as reduzirá para um único caractere.
  2. Se a operadora não contiver os caracteres da mensagem na ordem correta, o programa poderá retornar nada, a própria operadora ou um erro.
  3. Você pode supor que a mensagem e a operadora sejam sequências ASCII não vazias.
  4. A capitalização é importante: A não é equivalente a.
  5. Quando mais de um pacote é válido, seu programa pode gerar um ou todos eles.
  6. O espaço é um personagem como qualquer outro personagem.

Casos de teste:

Pacote de suporte de mensagem
"oi" "chegou?" "ele surgiu?" OU "ele chegou?"
"senhor" "chegou?" "hass iit chegou?"
"foo" "chegou?" "" OU "chegou?" OU um erro.
"Carro" "Gatos são legais." "CCaats arre col."
"car" "Gatos são legais." "" OU "Gatos são legais." OU um erro.
"Sofá" "Sofá" "CCoouucchh"
"oo" "oooooooooo" "oooo"
"o o" "oooo oooa" "oo ooa"

Isso é código de golfe, e o menor número de bytes vence.


5
Não suspeito nada ...: P
Quintec 08/12/18

É "oooo oa"(com 2 lugares) uma saída válida para o último caso de teste?
Arnauld

3
Não é uma saída válida porque a ordem dos caracteres duplicados no pacote deve corresponder à ordem dos caracteres na mensagem. Na mensagem, temos um 'o', então um '', em seguida, um 'o', mas o seu pacote tem o espaço após os o
jkpate

Ah sim, isso faz sentido.
Arnauld

1
Não. Meu raciocínio por trás dessa regra é que a saída do programa, no caso de nenhuma solução, deve ser inequívoca de que nenhuma solução é possível. As três saídas permitidas são inequívocas, mas seria necessária uma verificação mais extensa para o caso deduplicado.
Jkpate

Respostas:


5

Gelatina , 28 bytes

ẹⱮŒp<ƝẠ$ƇṪ
nƝ+çṬ¥a⁸ḟ0Ḥç¦ð¹ç?

Um programa completo que recebe carriere messagecomo argumentos de linha de comando que imprime o resultado
(para um não empacotável messageimprime o inalterado carrier).

Experimente online! Ou veja a suíte de testes .

Quão?

ẹⱮŒp<ƝẠ$ƇṪ - Link 1, helper function to find the indices to double: carrier, message
           -                               e.g. "programming", "rom"
 Ɱ         - map across message with:
ẹ          -   indices of                       [[2,5], [3], [7,8]]
  Œp       - Cartesian product                  [[2,3,7],[2,3,8],[5,3,7],[5,3,8]]
        Ƈ  - filter keep if:
       $   -   last two links as a monad:
     Ɲ     -     for neighbours:
    <      -       less than?                    [1,1]   [1,1]   [0,1]   [0,1]
      Ạ    -     all truthy?                     1       1       0       0
           -                                    [[2,3,7],[2,3,8]]
         Ṫ - tail (if empty yields 0)                    [2,3,8]

nƝ+çṬ¥a⁸ḟ0Ḥç¦ð¹ç? - Main Link: carrier, message
                ? - if...
               ç  - ...condition: last Link (the helper function) as a dyad
             ð    - ...then: perform the dyadic chain to the left (described below)
              ¹   - ...else: do nothing (yields carrier)
                  - (the then clause:)
 Ɲ                - for neighbours in the carrier
n                 - not equal?
     ¥            - last two links as a dyad:
   ç              -   call last Link (the helper function) as a dyad
    Ṭ             -   untruth (e.g. [2,5] -> [0,1,0,0,1])
  +               - add (vectorises)
      a⁸          - logical AND with carrier
        ḟ0        - filter out zeros
            ¦     - sparse application...
           ç      - ...to indices: call last Link (the helper function) as a dyad
          Ḥ       - ...do: double (e.g. 'x' -> 'xx')

3

JavaScript (ES6), 71 bytes

Toma entrada como (message)(carrier).

s=>g=([c,...C],p)=>c?(c==s[0]?(s=s.slice(1),c)+c:p==c?'':c)+g(C,c):s&&X

Experimente online!


Versão alternativa, 66 bytes

Se pudermos considerar a mensagem como uma matriz de caracteres:

s=>g=([c,...C],p)=>c?(c==s[0]?s.shift()+c:p==c?'':c)+g(C,c):s+s&&X

Experimente online!


Edit : Obrigado ao @tsh por perceber que eu esqueci de remover algum código ao mudar de versões não recursivas para recursivas.


Você pode remover p=uma vez que p é passado por um parâmetro.
tsh

@tsh Oops. É algum código residual das versões anteriores, não recursivas, que eu esqueci de remover. Obrigado!
Arnauld

2

Haskell, 124 121 107 101 97 95 90 bytes

(#).(++"ü")
"ü"#[]=[]
p@(m:n)#e@(c:d)|m/=c=c:p#snd(span(==c)d)|m==n!!0=m:m:n#d|1<2=m:n#e

Gera a exceção "Padrões não exaustivos" se a transportadora não contiver a mensagem.

Experimente online!

Edit: -5 bytes graças a @Laikoni.


Eu acho que mudar os casos permite que você solte m==c: Experimente online!
Laikoni

1

Retina 0.8.2 , 67 bytes

+`(.)(\1*)\1*(.*¶)(?(\1)(\1(\2)))(.*)$(?!¶)
$1$4$5¶$3$6
M!s`.*¶$
¶

Experimente online! Leva a operadora na primeira linha e a mensagem na segunda linha. Explicação:

+`(.)(\1*)\1*(.*¶)(?(\1)(\1(\2)))(.*)$(?!¶)
$1$4$5¶$3$6

Processar execuções de 1 ou mais caracteres idênticos da transportadora. Se também houver uma execução de 1 ou mais dos mesmos caracteres na mensagem, acrescente a menor das duas execuções à saída em duplicado, caso contrário, adicione um único caractere da portadora à saída. Cada execução de caracteres de saída é finalizada com uma nova linha para distingui-la da entrada. O (?!¶)final impede que o regex pense que a operadora é a mensagem assim que a mensagem estiver esgotada, pois normalmente $é permitido combinar onde ¶$corresponderia.

M!s`.*¶$

Exclua tudo se a mensagem não estiver completamente codificada.

Remova as novas linhas da saída.


Eu acho que não passa do penúltimo caso de teste (o que, para ser justo, eu não tinha no post inicial).
Jkpate

@jkpate Obrigado por apontar isso; Eu tive que reescrever minha abordagem um pouco.
Neil

0

Limpo , 118 bytes

import StdEnv,StdLib
$[][]=[]
$[u:v]b#(_,w)=span((==)u)v
|b%(0,0)==[u]=[u,u: $if(v%(0,0)<>b%(1,1))w v(tl b)]=[u: $w b]

Experimente online!

Leva o transportador primeiro, depois a mensagem.

Erros com Run time error, rule '$;2' in module 'main' does not matchse a mensagem não couber.


0

Ruby , 73 bytes

f=->m,c,b=p{x,*c=c;x ?(x==m[0]?x+m.shift: x==b ?'':x)+f[m,c,x]:m[0]?x:''}

Experimente online!

Função recursiva, recebe entradas como matriz de caracteres.

Pela primeira vez, eu esperava usar o squeezemétodo interno do Ruby, que contrai execuções consecutivas do mesmo caractere para uma única instância. Mas, infelizmente, não - os dois últimos casos de teste estragaram tudo tão mal, que tive que recorrer a uma abordagem completamente diferente, e isso acabou sendo basicamente uma porta da resposta de Arnauld .


0

Powershell, 134 bytes

param($m,$c)$c-csplit"([$m])"|%{$i+=$o=$_-ceq$m[+$i]
if($o-or$_-cne"`0$h"[-1]){$h+=($_-replace'(.)(?=\1)')*($o+1)}}
$h*!($i-$m.Length)

O script retorna o empty string se a operadora não contiver os caracteres da mensagem na ordem correta.

Script de teste com menos golfe:

$f = {

param($message,$carrier)
$carrier-csplit"([$message])"|%{                # split by chars of the message, chars itself included ([])
    $offset=$_-ceq$message[+$i]                 # 0 or 1 if current substring is a current message char (case-sensitive equality)
    $i+=$offset                                 # move to next message char if need it
    if($offset-or$_-cne"`0$h"[-1]){             # condition to remove redundant doubles after message char: arrrived -> arrived, ooo -> oo, etc
                                                # `0 to avoid exception error if $h is empty
        $h+=($_-replace'(.)(?=\1)')*($offset+1) # accumulate a double message char or a single substring without inner doubles: arried -> arived, anna -> ana, etc
    }
}
$h*!($i-$message.Length)                        # repeat 0 or 1 times to return '' if the carrier does not contain the message characters in the right order

}

@(
    ,('hi'         ,'has it arrived?'    ,'hhas iit arived?', 'hhas it ariived?')
    ,('hi?'        ,'has it arrived?'    ,'hhas iit arived??', 'hhas it ariived??')
    ,('sir'        ,'has it arrived?'    ,'hass iit arrived?')
    ,('foo'        ,'has it arrived?'    ,'')
    ,('Car'        ,'Cats are cool.'     ,'CCaats arre col.')
    ,('car'        ,'Cats are cool.'     ,'')
    ,('Couch'      ,'Couch'              ,'CCoouucchh')
    ,('oo'         ,'oooooooooo'         ,'oooo')
    ,('o o'        ,'oooo oooa'          ,'oo  ooa')
    ,('er'         ,'error'              ,'eerorr', 'eerror')
    ,('a+b'        ,'anna+bob'           ,'aana++bbob')
) | % {
    $message,$carrier,$expected = $_
    $result = &$f $message $carrier
    "$($result-in$expected): $result"
}

Resultado:

True: hhas iit arived?
True: hhas iit arived??
True: hass iit arrived?
True:
True: CCaats arre col.
True:
True: CCoouucchh
True: oooo
True: oo  ooa
True: eerror
True: aana++bbob

0

C (gcc) , 69 + 12 = 81 bytes

g(char*m,char*_){for(;*_;++_)*m-*_?_[-1]-*_&&p*_):p p*m++));*m&&0/0;}

Compilar com (12 bytes)

-Dp=putchar(

Experimente online!

g(char*m,char*_){
    for(;*_;++_)        //step through _
        *m-*_?          //check if character should be encoded
            _[-1]-*_&&  //no? skip duplicates
                p*_)    //    print non-duplicates
        :p p*m++));     //print encoded character twice
    *m&&0/0;            //if m is not fully encoded, exit via Floating point exception
}
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.