Faire une montagne d'une taupinière

12

On vous donne une chaîne de terrain, avec des taupinières et des montagnes:

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

Votre travail consiste à remplacer chaque taupinière de la chaîne par une montagne équivalente centrée dans la même colonne. Le reste de la chaîne ne doit pas être affecté. Cela peut nécessiter des lignes supplémentaires au début de la chaîne.

Une taupinière se compose de colonnes adjacentes où le terrain monte, immédiatement suivies de colonnes adjacentes où le terrain descend. Le côté le plus court doit avoir exactement une colonne de large.

Ce sont tous des taupinières:

_____/\______

   /\________
__/

________/\
          \__

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

Ce ne sont pas des taupinières:

    /\
___/  \______

      ___
_____/   \___

____  _______
    \/

Une montagne est comme une taupinière, mais le côté le plus court a quatre lignes de hauteur au lieu d'une.

Exemples

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

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

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

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

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

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

Règles supplémentaires

  • Les failles standard sont interdites.
  • L'entrée et la sortie peuvent être dans n'importe quel format raisonnable.
  • Vous pouvez supposer la présence ou l'absence d'espaces de fin dans la chaîne d'entrée.
  • Il y aura toujours suffisamment d'espace sur les côtés de la chaîne ainsi qu'entre les taupinières pour toutes les montagnes dont vous pourriez avoir besoin.
  • Si le remplacement des taupinières par des montagnes crée des taupinières supplémentaires, vous n'avez pas besoin de transformer ces taupinières en montagnes.
  • Le terrain ne peut pas monter et descendre dans la même colonne. Si cela se produit, le terrain ne bouge pas.
  • Si une colonne particulière ne fait pas partie d'une montagne, sa hauteur doit rester inchangée.

Il s'agit de , donc la réponse la plus courte en octets l'emporte.

RamenChef
la source
C'est un beau défi!
Galen Ivanov
Je pense que l'avant-dernier exemple devrait se terminer par quatre \ et quatre _ et non sept \ et un _.
ngm
1
Votre intention est-elle que les premier et dernier caractères ne changent pas la position verticale et aussi que le moins de caractères possible soit changé ? C'est ce que suggèrent les exemples, surtout si l'avant-dernier est la seule bonne réponse.
ngm
1
Ce serait une bonne idée de modifier la spécification du défi pour clarifier ces points.
ngm
1
De plus, la dernière règle «le terrain ne peut pas monter et descendre dans la même colonne» - qu'est-ce que cela signifie? "Le terrain" n'est sûrement qu'un des trois personnages /, \, _, alors comment pourrait-il monter et descendre en même temps?
Chas Brown

Réponses:

2

Python 2 , 509 495 480 octets

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

Essayez-le en ligne!

Pas encore clair quelles sont les règles réelles; mais voici les contraintes supplémentaires qui sont imposées au-delà de la règle selon laquelle les taupinières doivent être transformées en montagnes:

  • Les premier et dernier caractères de terrain de la sortie doivent être _, tout comme ils doivent l'être pour des entrées valides.
  • La différence verticale entre le premier _et le dernier _doit être maintenue entre l'entrée et la sortie.
  • Après les substitutions de la transformation des taupinières en montagnes, certains autres caractères pourraient devoir être modifiés afin de maintenir ladite différence verticale; mais les personnages modifiés ne doivent pas être des personnages faisant partie de montagnes créées à partir de taupinières.
  • Et lorsque vous effectuez ces modifications, le nombre de caractères supplémentaires modifiés doit être minimal.

Algorithme non golfé:

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
la source
1

Rouge , 855, 845 833 octets

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

Essayez-le en ligne!

Loin, très loin d'une solution golfique ... Il passe les cas de test mais échouerait très probablement sur un autre schéma plus étrange.

Plus lisible:

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
la source