Hacer una montaña de un Molehill

12

Te dan una cadena de terreno, con topes y montañas:

                        /\
                       /  \
              _/\__   /    \
          ___/     \_/      \_
____/\___/                    \___

Su trabajo es reemplazar cada molehill en la cadena con una montaña equivalente centrada en la misma columna. El resto de la cadena no debe verse afectado. Esto puede requerir líneas adicionales al comienzo de la cadena.

Un molehill consiste en columnas adyacentes donde el terreno sube, seguido inmediatamente por columnas adyacentes donde el terreno baja. El lado más corto debe tener exactamente una columna de ancho.

Estas son todas las molehills:

_____/\______

   /\________
__/

________/\
          \__

\           /
 \         /
  \       /
   \     /
    \/\_/

Estos no son molehills:

    /\
___/  \______

      ___
_____/   \___

____  _______
    \/

Una montaña es como un molehill, pero el lado más corto tiene cuatro líneas de altura en lugar de una.

Ejemplos

                  /\
                 /  \
           ->   /    \
____/\____    _/      \_

                       /\
                      /  \
                     /    \
           __ ->    /      \__
_     /\__/      __/
 \___/

                         /\
                        /  \
               ->      /    \
  /\                /\/      \
_/  \__/\_____    _/          \_

_                _    _                _
 \              /      \      /\      /
  \            /        \    /  \    /
   \          /          \  /    \  /
    \        /     ->     \/      \/
     \      /
      \    /
       \/\/

                             /\      /\
                            /  \    /  \
                           /    \  /    \
_                     -> _/      \/      \
 \                                        \
  \                                        \
   \/\______/\_______                       \_

                        /\                           /\       /\
                       /  \               /\        /  \     /  \
              _/\__   /    \       ->    /  \      /    \   /    \
          ___/     \_/      \_          /    \  __/      \_/      \_
____/\___/                    \___    _/      \/                    \___

Reglas Adicionales

  • Lagunas estándar están prohibidas.
  • La entrada y salida pueden estar en cualquier formato razonable.
  • Puede suponer la presencia o ausencia de espacios en blanco finales en la cadena de entrada.
  • Siempre habrá suficiente espacio en los lados de la cuerda, así como entre las colinas para cualquier montaña que pueda necesitar.
  • Si reemplazar las molehills con montañas crea molehills adicionales, no es necesario convertir esas molehills en montañas.
  • El terreno no puede subir ni bajar en la misma columna. Si esto sucede, el terreno no se mueve.
  • Si una columna en particular no se convierte en parte de una montaña, su altura debe permanecer sin cambios.

Este es el , por lo que gana la respuesta más corta en bytes.

RamenChef
fuente
Este es un buen desafío!
Galen Ivanov
Creo que el penúltimo ejemplo debería terminar con cuatro \ y cuatro _ y no siete \ y uno _.
ngm
1
¿Es su intención que el primer y el último carácter no cambien de posición vertical y también que se modifique el menor número posible de caracteres ? Esto parece ser lo que sugieren los ejemplos, especialmente si el segundo último es la única respuesta correcta.
ngm
1
Sería una buena idea editar la especificación de desafío para aclarar estos puntos.
ngm
1
Además, la última regla "el terreno no puede subir ni bajar en la misma columna", ¿qué significa eso? Seguramente "el terreno" es solo uno de los tres personajes /, \, _, entonces, ¿cómo podría subir y bajar al mismo tiempo?
Chas Brown

Respuestas:

2

Python 2 , 509 495 480 bytes

def f(S):
 B='\\';F='/';s=''.join(map(max,*S.split('\n')));t=list(re.sub(r'..((./\\[^\\])|([^/]/\\.))..',r'////\\\\\\\\',s));C=s.count;D=t.count;d=C(F)-D(F)+D(B)-C(B);m=[{'_':F,B:'_'},{'_':B,F:'_'}][d<0];d=abs(d);i=1
 while d:
	if s[i]!=t[i]:i+=7
	elif t[i]in m:d-=1;t[i]=m[t[i]]
	i+=1
 return'\n'.join(u for u in map(''.join,zip(*[u.ljust(2*len(S))for u in reduce(lambda (a,p),c:(a+[' '*[p,p-1][c==B]+c],p+[[0,-1][c==B],1][c==F]),t,([],len(t)))[0]]))[::-1]if u.strip())
import re

Pruébalo en línea!

Todavía no está claro cuáles son las reglas reales; pero aquí están las restricciones adicionales que se aplican por encima y más allá de la regla de que las colinas se convertirán en montañas:

  • Los caracteres de terreno primero y último de la salida deben ser _, tal como deben ser para entradas válidas.
  • La diferencia vertical entre el primero _y el último _debe mantenerse entre la entrada y la salida.
  • Después de las sustituciones de convertir los topes en montañas, es posible que sea necesario cambiar algunos otros caracteres para mantener dicha diferencia vertical; pero los personajes cambiados no deben ser ninguno de los personajes que forman parte de las montañas que se crearon a partir de las colinas.
  • Y al lograr estos cambios, el número de caracteres adicionales cambiados debe ser mínimo.

Algoritmo no golfista:

def f(s):
    s = ''.join(map(max,*s.split('\n'))) # flatten into a single line
    t = re.sub(r'..((./\\[^\\])|([^/]/\\.))..',r'////\\\\\\\\',s) # replace molehills with mountains
    d = s.count('/')-t.count('/')+t.count('\\')-s.count('\\') # are the two strings equally balanced?
    m=[{'_':'/','\\':'_'},{'_':'\\','/':'_'}][d<0] # make an appropriate mapping...
    d=abs(d);i=1 # skip over leading '_'...
    while d: # while still unbalanced...
        if s[i]!=t[i]:i+=7 # skip over any created mountains (7+1==8)
        elif t[i] in m:d-=1;t = t[:i]+m[t[i]]+t[i+1:] # if can replace, do replace
        i += 1 # next char
    t = reduce(lambda (a,p),c:(a+[' '*[p,p-1][c=='\\']+c],p+[[0,-1][c=='\\'],1][c=='/']),t,([],len(t)))[0]  # pad spaces at left side
    t = map(''.join,zip(*[u.ljust(max(map(len,t))) for u in t])) # rotate
    return '\n'.join(u for u in t[::-1] if u.strip()) # reverse and join into lines.
import re
Chas Brown
fuente
1

Rojo , 855, 845 833 bytes

func[s][r: split s"^/"c: charset"\_/"m: copy #()repeat n l: length? r[parse r/:n[any[i:
c(put m 1 + offset? r/:n i reduce[first i n])| skip]]]m: extract next sort/skip to-block m
2 2 e: copy[]parse b: rejoin collect[foreach c m[keep c/1]][any[c:["/\_"|"/\/"](alter
e 1 + offset? b c)| c:["_/\"|"\/\"](alter e 2 + offset? b c)| skip]]y: 0 foreach a e[q: p:
d: -3 + min m/(a - 4)/2 m/(a + 5)/2 if d < y[y: d]j: i: a until[m/:i/1: #"/"m/:i/2: p k: i
- 2 if all[k > 0 #"_"= m/:k/1 p = m/:k/2][m/(k + 1)/1: #"_"m/(k + 1)/2: p break]i: i - 1
m/:i/2 < p: p + 1]j: j + 1 until[m/:j/1: #"\"m/:j/2: q k: i + 2 if all[#"_"= m/:k/1
p = m/:k/2][m/(k - 1)/1: #"_"m/(k - 1)/2: p break]j: j + 1 m/:j/2 < q: q + 1]]y: y - 1 q:
collect[loop l - y[k: copy""keep pad k p: length? m]]repeat n p[w: m/1/2 - y
q/:w/:n: m/1/1 m: next m]foreach d q[print d]]

Pruébalo en línea!

Lejos, muy lejos de una solución de golf ... Pasa los casos de prueba, pero probablemente fallaría en algún otro patrón más extraño.

Más legible:

f: func [ s ] [
    r: split s "^/"
    c: charset "\_/"
    m: copy #()
    repeat n l: length? r[
        parse r/:n[ any [ i: c(put m 1 + offset? r/:n i reduce[ first i n ])
        | skip]]
    ]
    m: sort/skip to-block m 2
    m: extract next m 2
    b: rejoin collect [ foreach c m [ keep c/1 ] ]
    e: copy []
    parse b [ any [ c: [ "/\_" | "/\/" ]
                (alter e 1 + offset? b c)
            | c: [ "_/\" | "\/\" ]
                (alter e 2 + offset? b c)
            | skip
        ]
    ]
    y: 0
    foreach a e [
        q: p: d: -3 + min m/(a - 4)/2 m/(a + 5)/2
        if d < y [ y: d ]
        j: i: a
        until [
            m/:i/1: #"/"
            m/:i/2: p
            k: i - 2
            if all [ k > 0
                     #"_" = m/:k/1
                     p = m/:k/2
            ] [ 
                m/(k + 1)/1: #"_"
                m/(k + 1)/2: p
                break
            ]
            i: i - 1
            p: p + 1 
            m/:i/2 < p
        ]
        j: j + 1
        until[
            m/:j/1: #"\"
            m/:j/2: q
            k: i + 2
            if all [ #"_" = m/:k/1 
                     p = m/:k/2
            ] [
                m/(k - 1)/1: #"_"
                m/(k - 1)/2: p
                break
            ]
            j: j + 1
            q: q + 1 
            m/:j/2 < q
        ]
    ]
    y: y - 1
    q: collect [
        loop l - y [
            k: copy ""
            keep pad k p: length? m
        ]
    ]
    repeat n p [ w: m/1/2 - y
                 q/:w/:n: m/1/1
                 m: next m ]
    foreach d q [ print d ]
]
Galen Ivanov
fuente