Membuat Gunung dari Molehill

12

Anda diberi serangkaian medan, dengan molehill dan gunung:

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

Tugas Anda adalah mengganti setiap molehill dalam string dengan gunung setara yang berpusat di kolom yang sama. Sisa string harus tidak terpengaruh. Ini mungkin memerlukan baris tambahan di awal string.

Sebuah molehill terdiri dari kolom yang berdekatan di mana medan naik, segera diikuti oleh kolom yang berdekatan di mana medan turun. Sisi terpendek harus tepat satu lebar kolom.

Ini semua adalah molehills:

_____/\______

   /\________
__/

________/\
          \__

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

Ini bukan molehills:

    /\
___/  \______

      ___
_____/   \___

____  _______
    \/

Sebuah gunung seperti molehill, tetapi sisi terpendek adalah empat garis, bukan satu.

Contohnya

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

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

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

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

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

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

Aturan tambahan

  • Celah standar dilarang.
  • Input dan output dapat dalam format apa pun yang masuk akal.
  • Anda dapat mengasumsikan ada atau tidaknya spasi spasi di string input.
  • Akan selalu ada ruang yang cukup di sisi-sisi tali dan juga di antara molehills untuk setiap gunung yang mungkin Anda butuhkan.
  • Jika mengganti molehills dengan gunung menciptakan molehills tambahan, Anda tidak perlu mengubah molehills tersebut menjadi pegunungan.
  • Medan tidak bisa naik dan turun di kolom yang sama. Jika ini terjadi, medannya tidak bergerak.
  • Jika kolom tertentu tidak menjadi bagian dari gunung, ketinggiannya harus tetap tidak berubah.

Ini adalah , jadi jawaban tersingkat dalam byte menang.

RamenChef
sumber
Ini tantangan yang bagus!
Galen Ivanov
Saya pikir contoh kedua terakhir harus diakhiri dengan empat \ dan empat _ dan bukan tujuh \ dan satu _.
ngm
1
Apakah niat Anda bahwa karakter pertama dan terakhir tidak boleh mengubah posisi vertikal dan juga bahwa karakter sesedikit mungkin harus diubah ? Ini tampaknya seperti yang disarankan oleh contoh, terutama jika jawaban terakhir yang kedua adalah satu-satunya jawaban yang benar.
ngm
1
Sebaiknya edit spesifikasi tantangan untuk mengklarifikasi poin-poin ini.
ngm
1
Selain itu, aturan terakhir "medan tidak bisa naik dan turun di kolom yang sama" - apa artinya itu? Tentunya "medan" hanya satu dari tiga karakter /, \, _, jadi bagaimana mungkin ia bisa naik turun pada saat yang sama?
Chas Brown

Jawaban:

2

Python 2 , 509 495 480 byte

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

Cobalah online!

Masih belum jelas aturan apa yang sebenarnya; tetapi di sini ada kendala tambahan yang ditegakkan di atas dan di luar aturan bahwa molehills akan diubah menjadi gunung:

  • Karakter medan pertama dan terakhir dari output harus _, sama seperti mereka harus untuk input yang valid.
  • Perbedaan vertikal antara yang pertama _dan yang terakhir _harus dipertahankan antara input dan output.
  • Setelah penggantian dari mengubah molehills menjadi pegunungan, beberapa karakter lain mungkin perlu diubah untuk mempertahankan perbedaan vertikal tersebut; tetapi karakter yang diubah tidak boleh dari karakter yang merupakan bagian dari gunung yang dibuat dari molehills.
  • Dan ketika melakukan perubahan ini, jumlah karakter tambahan yang diubah harus minimal.

Algoritma Tidak Digabungkan:

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
sumber
1

Merah , 855, 845 833 byte

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

Cobalah online!

Jauh, jauh dari solusi golf ... Ini melewati test case tetapi kemungkinan besar akan gagal pada beberapa pola lain yang lebih aneh.

Lebih mudah dibaca:

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
sumber