Pensando fuera de la caja - ¿Lo estoy haciendo bien?

59

Sigo escuchando que pensar fuera de la caja es un objetivo que vale la pena alcanzar, pero ¿cómo puedo saber si lo estoy haciendo con éxito?

Para resolver este dilema, ya escribí un traductor de Brainwave a ASCII que, en teoría, debería producir resultados como

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

o

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

lo que hace que sea bastante fácil saber si uno está pensando fuera de la caja o no. (No #forman parte de la salida y representan nuevas líneas).

Sin embargo, debido a un error, a veces solo se devuelve una sección más pequeña de la salida:

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

        #
       +#
       |#
inking |#

    #
    #

La tarea

Por favor, ayúdenme a clasificar automáticamente la salida del traductor de Brainwave a ASCII escribiendo un programa o función que lea una representación ascii y devuelva si thinkingestá en el cuadro, fuera de él o si no puede distinguirlo de la entrada.

Entrada

Un conjunto de cadenas de la misma longitud como una lista o delimitadas por nuevas líneas que contienen

  • la cadena thinkingo pre o sufijos válidos de la misma
  • los caracteres que +-|forman una caja rectangular o partes válidas de ella
  • espacios
  • NO# , solo se incluyen en el desafío para marcar los extremos de las líneas de entrada.

Salida

  • un valor verdadero si thinkingestá fuera de la caja
  • un valor falso si thinkingestá en el cuadro
  • una clara tercera quizás valor si no puede determinarse a partir de la entrada si thinkingestá en la caja o no

Ejemplos

Verdad:

                   #
 +------+          #
 |      | 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 cadena:

"                   \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 cadena:

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

Tal vez:

thinking#

g|#

think#
-----#

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

   +--#
   |  #

# (empty input)

Como entrada de cadena:

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

Reglas

  • Este es el , así que trate de usar la menor cantidad de bytes posible.
  • El valor quizás se puede elegir libremente siempre que sea diferente del valor verdadero / falso y sea el mismo para todas las entradas quizás. También puede ser un error.
  • Puede suponer que la entrada siempre es válida (por ejemplo, no contiene más caracteres que +-ghiknt|, no más de un cuadro, ...).
Laikoni
fuente
Idea para un caso de prueba veraz: +\n+caja demasiado pequeña para una palabra
Destructible Lemon
@DestructibleWatermelon Gracias, agregaré un caso de prueba similar.
Laikoni
No tiene los casos más básicos en sus casos de prueba. ¿Te importaría incluir toda la caja con pensar en ella y toda la caja con la palabra entera pensando fuera de ella?
ATaco
¿Existe la posibilidad de que la palabra se superponga al cuadro (pensando en el cuadro )?
Mukul Kumar
17
Este es un caso límite de pesadilla, Dios.
Magic Octopus Urn

Respuestas:

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)))

La función fdevuelve true, falseo -1como su valor "quizás". Debe llamarse con un argumento: la entrada. Los otros dos parámetros solo existen para acortar el código.

Aquí hay una versión menos golfizada con comentarios:

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;
};

Me divertí mucho con este. ¡Gracias!

Editar: Guardado 6 bytes gracias @L. Serné modificando bpara usar un argumento predeterminado, guardando 3 bytes y cambiando [a-z]a \w, guardando 3 bytes más. También salvado 5 bytes más haciendo que la palabra de sustitución no global, el ahorro de 1 byte, y cambiando "a"a 5y ","a 4, el ahorro de 4 bytes.

kyle1320
fuente
Tratado con console.log(f("input")). Parece funcionar. Gran trabajo en golf esto.
devRicher
Buen trabajo en la respuesta. Traté de responder esto, y me quedé atrapado a medio camino. Noté 2 pequeños ahorradores de bytes: cambie b=(b,c)a b=(b,c=""), y luego puede eliminar el último argumento de las dos llamadas a bcon una cadena vacía como segundo argumento, ahorrando (2 * 3-3 =) 3 bytes en total. Además, puede acortar la palabra regex de [a-z]+a \w+(haga esto antes de que el otro reemplace, porque esto también coincidirá con los dígitos) ahorrando 3 bytes más.
Lucas
¡Bienvenido a PPCG y buena primera respuesta!
Kritixi Lithos
Recompensa otorgada. La respuesta más corta Buen trabajo, increíble respuesta.
devRicher
8

Python 2.7, 532 494 453 bytes

Este seguro tenía muchos casos especiales. Mis valores de verdad y falsedad son las cadenas "Verdadero" y "Falso" respectivamente. Mi valor quizás es un Error de índice, ya que son fáciles de activar y uno de mis casos de prueba lo activa si la entrada es una cadena vacía, que de todos modos es un caso probable. Hice uso de expresiones regulares bastante.

No practico golf en Python a menudo, así que estoy seguro de que esto podría reducirse aún más, pero aquí está mi 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]

En mi versión de golf, muestro la respuesta Verdadero / Falso llamando exit(bool as string). Aquí hay una versión comentada, en la que las declaraciones de salida se reemplazan con declaraciones de retorno, y todo se ha movido a una función:

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()

Mi solución asume que la entrada es válida, es decir, 'Thinking' (o sus subcadenas) están escritas correctamente, solo hay un cuadro, etc.

Editar: ahorró 10 bytes gracias a la sugerencia de @ ais523 de cambiar ca i.count('+'), 3 bytes gracias a la sugerencia de @ Pavel de reemplazar Truecon 1<2y Falsecon 2>1, 23 bytes eliminando un bloque innecesario y 2 bytes eliminando algunos espacios.

Edición 2: ahorré 36 bytes gracias a @Wheat Wizard que señaló amablemente que mis 'pestañas' eran en realidad 5 espacios (¡Oh!) Y sugirió algunas otras mejoras.

ren
fuente
2
Impresionante. Alguien realmente lo hizo.
devRicher
1
Creo que inunca cambia, ¿verdad? Por lo tanto, probablemente podría guardar algunos bytes almacenando i.count('+')en clugar de i.count, ya que nunca lo llama con ningún argumento, pero +.
1
Puede reemplazar verdadero y falso con 1 <2 y 2 <1, ¿verdad?
Pavel
1
No tiene que devolver el carro y sangrar en la definición de su función. Por lo que puedo decir, estás usando 4 espacios para la sangría. Puede sangrar a profundidad uno usando un solo espacio y profundidad 2 con una sola pestaña.
Wheat Wizard
@WheatWizard bueno, esto es vergonzoso ... parece que Atom estaba convirtiendo pestañas a 4 espacios. Gracias por el consejo, ¡recortó 36 bytes!
ren
8

Befunge, 535 bytes

Esto no es bonito y no se acerca a competir con las respuestas existentes, pero es lo mejor que podría lograr en Befunge.

Devuelve 1si pensar fuera de la caja, 0si pensara en el interior de la caja, y -1para tal .

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<

Pruébalo en línea!

James Holderness
fuente