Pensando fora da caixa - estou fazendo certo?

59

Continuo ouvindo que pensar fora da caixa é um objetivo que vale a pena atingir, mas como posso saber se estou conseguindo fazer isso com sucesso?

Para resolver esse dilema, já escrevi um tradutor de ondas cerebrais para ASCII que, em teoria, deveria produzir resultados como

                    #
   +------------+   #
   |   thinking |   #
   |            |   #
   +------------+   #
                    #

ou

                   #
 +------+          #
 |      | thinking #
 |      |          #
 |      |          #
 +------+          #
                   #

o que torna bastante fácil saber se alguém está pensando fora da caixa ou não. (Eles #não fazem parte da saída e representam novas linhas.)

No entanto, devido a um erro, às vezes apenas uma seção menor da saída é retornada:

   |         |         #
   +---------+         #
    thinking           #

        #
       +#
       |#
inking |#

    #
    #

A tarefa

Por favor, ajude-me a classificar automaticamente a saída do tradutor Brainwave-to-ASCII , escrevendo um programa ou função que leia uma reprensentação ascii e retorne se thinkingestá na caixa, fora dela ou não pode ser detectado pela entrada.

Entrada

Um conjunto de cadeias de caracteres do mesmo comprimento como uma lista ou delimitadas por novas linhas contendo

  • a sequência thinkingou pré ou sufixos válidos
  • os caracteres que +-|formam uma caixa retangular ou partes válidas
  • espaços
  • NÃO# , elas estão incluídas apenas no desafio de marcar as extremidades das linhas de entrada.

Resultado

  • um valor verdadeiro se thinkingestiver fora da caixa
  • um valor falso se thinkingestiver na caixa
  • um terço distinto talvez valor, se não puder ser determinado a partir da entrada, thinkingesteja na caixa ou não

Exemplos

Verdade:

                   #
 +------+          #
 |      | thinking #
 |      |          #
 |      |          #
 +------+          #
                   #

   |         |         #
   +---------+         #
    thinking           #

        #
       +#
       |#
       |#
inking |#

thinking #
-------+ #

 ++ # (thinking is not in the box, so it must be outside)
 ++ # (this is also the smallest possible box)

+ #
 t#

+----+# (The box is not wide enough to contain "thinking")

---# (The box is not high enough to contain "thinking")
---#

Como entrada de string:

"                   \n +------+          \n |      | thinking \n |      |          \n |      |          \n +------+          \n                   "
"   |         |         \n   +---------+         \n    thinking           "
"        \n       +\n       |\n       |\ninking |"
"thinking \n-------+ "
" ++ \n ++ "
"+ \n t"
"+----+"
"---\n---"
"g++"
"k\n+"

Falsy:

                    #
   +------------+   #
   |   thinking |   #
   |            |   #
   +------------+   #
                    #

  +---------------#
  |               #
  |               #
  |   thinking    #

      | #
king  | #
------+ #

+---#
|thi#
+---#

-#
n#
-#

Como entrada de string:

"                    \n   +------------+   \n   |   thinking |   \n   |            |   \n   +------------+   \n                    "
"  +---------------\n  |               \n  |               \n  |   thinking    "
"      | \nking  | \n------+ "
"+---\n|thi\n+---"
"-\nn\n-"

Talvez:

thinking#

g|#

think#
-----#

|          |# (box large enough to possibly contain the string)
|          |#

   +--#
   |  #

# (empty input)

Como entrada de string:

"thinking"
"g|"
"|t"
"-\ni"
"h\n-"
"think\n-----"
"|          |\n|          |"
"   +--\n   |  "
""

Regras

  • Isso é , então tente usar o mínimo de bytes possível.
  • O valor talvez pode ser escolhido livremente, desde que seja diferente do valor verdade / falsidade e seja o mesmo para todas as entradas talvez. Também pode ser um erro.
  • Você pode assumir que a entrada é sempre válida (por exemplo, não contém outros caracteres além de +-ghiknt|, não mais que uma caixa, ...).
Laikoni
fonte
Idéia para o caso de teste de verdade:, +\n+caixa muito pequena para uma palavra #
Destructible Lemon
@DestructibleWatermelon Obrigado, vou adicionar um caso de teste semelhante.
Laikoni
Você não tem os casos mais básicos em seus casos de teste. Importa-se de incluir a caixa inteira com o pensamento nela e a caixa inteira com a palavra inteira pensando fora dela?
ATaco
Existe a possibilidade da palavra sobrepor a caixa (pensando na caixa )?
precisa
17
Este é um pesadelo de fronteira, caramba.
Magic Octopus Urn

Respostas:

11

JavaScript (ES6), 274 263 bytes

f=(a,b=(b,c="")=>a=a.replace(b,c),c=b=>b.test(`,${a},`))=>(b(/\w+/,5),b(/\+/g,1),b(/\-/g,2),b(/\|/g,3),b(/\n/g,4),c(/[13][2 ]{0,7}[13]|[12] *4 *[12]/)||(b(/ /g),b(/43+(?=4)/g),!c(/353|24542|12+435|21453|35412|5342+1/)&&(!c(/^([^1]*|([^15]*1){1,2}[^15]*)$/)||-1)))

A função fretorna true, falseou -1como seu "talvez" valor. Deve ser chamado com um argumento: a entrada. Os outros dois parâmetros existem apenas para encurtar o código.

Aqui está uma versão menos golfe com comentários:

var f = (input) => {
    var replace = (re, s) => input = input.replace(re, s);
    var test = re => re.test(input);

    /*
        Replace some "special" characters with ones that are shorter to put in a regex.
        "+" --> "1"
        "-" --> "2"
        "|" --> "3"
        "\n" --> ","
    */
    replace(/\+/g,1);
    replace(/\-/g,2);
    replace(/\|/g,3);
    replace(/\n/g,',');

    /*
        Shorten the word, if there is one, to just a single character "a".
    */
    replace(/[a-z]+/g,'a');

    /*
        Append a newline to the beginning and end of the input.
    */
    input = ','+input+',';

    /*
        Test the size of the box. These are the cases covered:
        /[13][2 ]{0,7}[13]/ : A horizontal edge or middle section has an inner width of fewer than 8 characters.
        /[12] *, *[12]/     : There are two horizontal edges in a row, with no space between.

        If either of these match, the word must be outside of the box. Return the truthy value (true).
    */
    if (test(/[13][2 ]{0,7}[13]|[12] *, *[12]/)) return true;

    /*
        Remove any spacing from the input. It it unnecessary from this point onwards.
    */
    replace(/ /g,'');

    /*
        Remove any lines with only vertical bars. These are also unnecessary.
    */
    replace(/,3+(?=,)/g,'');

    /*
        Edge / corner cases (heh). These are the cases covered:
        /3a3/    : two vertical bars with the word between.
        /2,a,2/  : two horizontal bars with the word between.
        /12+,3a/ : word inside the top left corner.
        /21,a3/  : word inside the top right corner.
        /3a,12/  : word inside the bottom left corner.
        /a3,2+1/ : word inside the bottom right corner.

        If any of these match, the word is inside the box. Return the falsy value (false).
    */
    if (test(/3a3|2,a,2|12+,3a|21,a3|3a,12|a3,2+1/)) return false;

    /*
        "Maybe" cases. These are the cases covered:
        /^[^1]*$/                : Input contains no corners, and may or may not contain a word.
        /^([^1a]*1){1,2}[^1a]*$/ : Input contains 1 or 2 corners, and no word.

        If either of these match, assuming the previous test cases have not been hit,
        we cannot tell if the word is inside or outside the box. Return the maybe value (-1).
    */
    if (test(/^([^1]*|([^1a]*1){1,2}[^1a]*)$/)) return -1;

    /*
        If none of the previous cases matched, the word must be outside of the box. Return the truthy value (true).
    */
    return true;
};

Nos divertimos muito com este. Obrigado!

Editar: salvou 6 bytes graças a @L. Serné modificando bpara usar um argumento padrão, economizando 3 bytes e alterando [a-z]para \w, economizando mais 3 bytes. Também salvou mais 5 bytes, tornando a substituição da palavra não global, economizando 1 byte e alterando "a"para 5e ","para 4, economizando 4 bytes.

kyle1320
fonte
Tentei com console.log(f("input")). Parece funcionar. Ótimo trabalho em jogar isso.
devRicher
Bom trabalho na resposta. Tentei responder a isso e fiquei preso no meio do caminho. Notei dois pequenos economizadores de bytes: mude b=(b,c)para b=(b,c="")e, em seguida, você pode remover o último argumento das duas chamadas bcom uma string vazia como segundo argumento, economizando (2 * 3-3 =) 3 bytes no total. Além disso, você pode reduzir a palavra regex de [a-z]+para \w+(faça isso antes que o outro substitua, porque isso também corresponderá a dígitos), economizando mais 3 bytes.
Lucas
Bem-vindo ao PPCG e boa primeira resposta!
Kritixi Lithos 2/17/17
Recompensa concedida. Resposta mais curta. Ótimo trabalho, resposta incrível.
precisa saber é o seguinte
8

Python 2.7, 532 494 453 bytes

Este com certeza teve muitos casos especiais. Meus valores de verdade e falsidade são as cadeias "Verdadeiro" e "Falso", respectivamente. Meu valor talvez é um erro de índice, pois é fácil de disparar e um dos meus casos de teste o aciona se a entrada for uma sequência vazia, o que é um caso talvez. Eu usei expressões regulares bastante.

Eu não jogo golfe em python com frequência, então tenho certeza de que isso poderia ser mais fácil, mas aqui está o meu código:

import re
def e(s):exit(str(s))
i=input()
T=1<2
F=2<1
a=len(i)+1
c=i.count('+')
s='[a-z]'
x=re.search
p=x(s,i)
k=x('\+.*'+s,i)
l=x(s+'.*\|',i)
r=x('\|.*'+s,i)
f=i.find('+')
g=i[f-1]=='-'and f>0
if x('\-.*\n.*\-',i):e(T)
if x('\+.{0,7}\+',i):e(T)
if c>1 and not p:i[a]
if c>3:e(not(r and l))
if c>0:
 if r and l:e(F)
 if g:
    if l:e(F)
    if p or k:e(T)
    i[a]
 if r or k:e(F)
 if p:e(T)
 i[a]
if x('-.*\s[a-z].*\s-',i):e(F)
if x('\|.*[a-z].*\|',i):e(F)
i[a]

Na minha versão de golfe, eu mostro a resposta Verdadeiro / Falso ligando exit(bool as string). Aqui está uma versão comentada, na qual as instruções de saída são substituídas por instruções de retorno e tudo foi movido para uma função:

import re
i=input()
T=True
F=False
def z():
    # some variables and shortcuts useful for testing

    # length of input +1. Used to throw an index out of bounds error on 'maybe'
    a=len(i)+1
    # c for i.Count()
    c=i.count
    # string used in regular expressions often
    s='[a-z]'
    # shorten regeX calls
    x=re.search
    # p is true is 'thinking' is Present on canvas
    p=x(s,i)
    # k is true if 'thinking' is Right of a 'Korner' (corner)
    k=x('\+.*'+s,i)
    # l is true if 'thinking' is Left of a pipe (|)
    l=x(s+'.*\|',i)
    # r is true if 'thinking' is right of a pipe
    r=x('\|.*'+s,i)
    # f is First corner (+) index
    f=i.find('+')

    # g is true if box is facing riGht (i.e. there is a dash before the first +)
    # for example, '---+' indicates the box faces right. if the + is the 0th
    # character, then the box must be facing left.
    # Note that this assignment also checks for the empty string 'maybe'
    # case, which is signalled by an IndexOutofBounds error
    # CASE 1: Empty Input
    # ex: ''
    g=i[f-1]=='-' and f>0

    # Begin testing all possible scenarios

    # CASE 2: Box is too short (vertically)
    # ex: ------
    #     ------
    if x('\-.*\n.*\-',i):return T

    # CASE 3: box is too short (horizontally)
    # ex: ||
    if x('\+.{0,7}\+',i):return T

    # CASE 4: box is not too short yet no corners (+) or text are present on canvas
    # ex:
    # |       |         --------
    # |       |   or
    # |       |         --------
    # this is a maybe case, so throw out of bounds error
    if c('+')>1 and not p:i[a]

    # CASE 5: Four corners visible (whole box visible)
    # ex: +---+
    #     | X |
    #     +---+
    # return false if text is both right of and left of pipes (i.e. in box)
    if c('+')>3:return not(r and l)

    # CASE 6: one or two corners visible
    # ex:
    # ----+        |    |          |
    #     |    or  +----+   or  ---+  etc
    # ----+
    # in this case, we idenify which way the box faces
    if c('+')>0:

        # CASE 6-A: Text is between two pipes
        # ex:
        #     |   X   |
        #     +-------+
        # if text is between pipes (box is extending from top or bottom of
        # canvas), then it is inside box
        if r and l:return F

        # CASE 6-B: Box faces right
        # if the box is riGht-facing, ex:
        # ----+
        #     |    or  ----+  etc
        # ----+            |
        if g:

            # CASE 6-B-a: Letters are left of a pipe or a + in a right facing box
            # ----+
            #  X  |   or  ----+
            # ----+         X |
            if l :return F

            # CASE 6-B-b: Letters are right of a pipe or + in a right facing box
            # ----+
            #     | X  or  ----+
            # ----+            | X
            if p or k:return T

            # CASE 6-B-c: right-facing otherwise
            # otherwise, it is a 'maybe' case
            # use an index out of bounds error to signal 'maybe'
            i[a]

        # CASE 6-C: Box faces left (or letters are on canvas yet not inside box)
        # ex:
        #   +----
        #   |        or   +---  or
        #   +----         |
        else:

            # CASE 6-C-a: Letters are right of a pipe or a + in a left facing box
            # if letters are right of pipe, they are inside box, ex:
            #   +----
            #   | X       or   +---  or X +---
            #   +----          | X        |
            if r or k:return F

            # CASE 6-C-b: Letters are left of a pipe in a left facing box
            # ex:
            #     +----
            #   X |        or     +---
            #     +----         X |

            # CASE 6-C-c: Letters are on canvas yet not left or right of
            # a pipe or a + (they must therefore be outside the box)
            # ex:
            #  |     |
            #  +-----+
            #     X
            if p:return T

            # CASE 6-C-d: text is not visible on canvas, and only part of the box is
            # ex:
            #  |     |
            #  +-----+
            #
            # this is a 'maybe' case, as text is off canvas
            # use an index out of bounds error to signal 'maybe'
            i[a]

    # CASE 7: No corners visible, nonempty input

    # CASE 7-A: No corners visible, letters sandwitched between dashes
    # ex:
    # -----
    #   X
    # -----
    # if there are no corners, yet letters are sandwitched between dashes,
    # then word is in box
    if x('-.*\s[a-z].*\s-',i):return F

    # CASE 7-B: No corners visible, letters sandwitched bewteen pipes
    # ex: |  X  |
    # in this case, word is inside box
    if x('\|.*[a-z].*\|',i):return F

    # If none of the above cases are met, it is a maybe, so throw the error
    i[a]

print z()

Minha solução pressupõe que a entrada é válida, ou seja, 'Thinking' (ou suas substrings) estão escritas corretamente, existe apenas uma caixa, etc.

Editar: salvou 10 bytes graças à sugestão de @ ais523 de mudar cpara i.count('+'), 3 bytes graças à sugestão de @ Pavel de substituir Truepor 1<2e Falsecom 2>1, 23 bytes removendo um bloco desnecessário e 2 bytes removendo alguns espaços.

Edit 2: Salvei 36 bytes graças ao @Wheat Wizard, que gentilmente apontou que minhas 'guias' eram na verdade 5 espaços (D'oh!) E sugeriu outras melhorias.

ren
fonte
2
Impressionante. Alguém realmente fez isso.
devRicher
11
Eu acho que inunca muda, certo? Portanto, você provavelmente poderia salvar alguns bytes armazenando i.count('+')em cvez de i.count, como nunca o chama com nenhum argumento, exceto +.
11
Você pode substituir verdadeiro e falso por 1 <2 e 2 <1, certo?
Pavel
11
Você não precisa retornar e recuar na definição de função. Tanto quanto posso dizer, você está usando 4 espaços para indentação. Você pode recuar para a profundidade um usando um único espaço e a profundidade 2 com uma única guia.
Wheat Wizard
@WheatWizard bem, isso é embaraçoso ... parece que o Atom estava convertendo guias em 4 espaços. Obrigado pelo conselho, ele cortou 36 bytes!
ren
8

Anterior, 535 bytes

Isso não é bonito e nem chega perto de competir com as respostas existentes, mas é o melhor que pude obter no Befunge.

Retorna 1se pensar fora da caixa, 0se pensar dentro da caixa, e -1para talvez .

p10p20p130p140p150p9-:60p70p"~":80p90pvp8p04+1:g04p03:$p9g04+g9g\<<
0$$$$"xxxx"5p041p031p$_v#!-+55:_v#`0:~<p05+1g
v01g04$_v#*`\"|"\`"-"::<>0g\8\p"0"-!!40g1-\8\p:4-!:00g0`*!:00g\6\p40g\8\p00g!*4v
>p50g20p>8%:30g88+*+:3-v4v\-1g05!!*-"3"\-"4"::p\7\g05!!-3:+*+88g8g04:p00+g00*g0<
v!*-"3"\-"5"::p\6\g04!!<!>>7\p::"C"-\"3"-*!!50g\9\p"0"-!!50g1-\9\p:5-!:40g9g48*v
>!40g1-\6\p::"S"-\"3"-*!^>0#4g#p9#\g#94#\8#g*#0-#5!#p*#\5#70#\g#-*^#84g9g04:!*`<
>80g60g-8`90g70g-1`**+!:10g80g`60g10g`20g90g`70g20g`+++!!*\!-.@
^!g01***`"}"g09`"}"g08`g070`g060<

Experimente online!

James Holderness
fonte