Намалюйте мої контури


25

Давши прямокутну матрицю висот, намалюйте її контури.

Завдання

Два елементи xі yзнаходяться на одному рівні контуру, якщо floor(x/10) == floor(y/10). Наприклад, 52і 58знаходяться на тому ж рівні контуру, але 58і 64не є.

Акт малювання контурів визначається наступним чином: Для кожного елемента eзамініть його дворядним рядком, вибраним так:

  • перший символ - це " "якщо елемент нижче eзнаходиться на тому ж рівні контуру, як eі якщо немає елемента внизу eта в "_"іншому випадку
  • другий символ полягає в тому " "випадку, якщо елемент праворуч eзнаходиться на тому ж рівні контуру, eабо немає елемента праворуч eі в "|"іншому випадку

Елементи всередині рядків з'єднуються разом, потім рядки з'єднуються між собою новими рядками.

Приклад

Скажімо, вхід є [[5,20],[3,6]], візуалізується як

5 20
3 6

Ми спочатку розглядаємо 5. Оскільки 3знаходиться на тому ж рівні контуру 5, що і перший символ " ". Оскільки 20не знаходиться на тому ж рівні контуру 5, що й другий символ "|".

Тепер ми дивимось 20. Оскільки 6не знаходиться на тому ж рівні контуру 20, що і перший символ "_". Оскільки праворуч від елемента немає 20, другий символ є " ".

Тепер ми дивимось 3. Оскільки внизу немає елемента 3, перший символ є " ". Оскільки 6знаходиться на тому ж рівні контуру 3, що і другий символ " ".

Тепер ми дивимось 6. Оскільки внизу немає елемента 6, перший символ є " ". Оскільки праворуч від елемента немає 6, другий символ є " ".

На основі цих двох знаків, ми робимо заміни, щоб отримати [[" |","_ "],[" "," "]]. Об’єднавши їх разом, ми отримуємо результат

 |_ 
    

Правила

  • Вхідна матриця завжди буде прямокутною і складається з натуральних чисел.
  • Пробіли або нові рядки можуть бути в будь-якій кількості (включаючи 0) і не повинні бути узгодженими жодним чином.
  • Вам не доведеться дотримуватися одного алгоритму, поки ви даєте однакові результати.
  • Ваша програма або функція може вивести рядок, відокремлений рядками, список рядків або еквівалент.
  • Це , тому найкоротший код у байтах виграє.

Випробування

input
output

[[1,5,8,9],[3,11,13,8],[7,14,10,9],[4,8,7,6]]
  _ _  
 |   | 
 |_ _| 

[[0,10,20,30,40,50,60,70,80,90],[0,0,10,10,20,20,30,30,40,40],[0,0,0,10,10,10,20,20,20,30],[0,0,0,0,10,10,10,10,20,20],[0,0,0,0,0,10,10,10,10,10],[0,0,0,0,0,0,10,10,10,10],[0,0,0,0,0,0,0,10,10,10],[0,0,0,0,0,0,0,0,10,10],[0,0,0,0,0,0,0,0,0,10],[0,0,0,0,0,0,0,0,0,0]]
 |_|_|_|_|_|_|_|_|_
   |_  |_ _|_ _|_ _
     |_    |_ _  |_
       |_      |_ _
         |_        
           |_      
             |_    
               |_  
                 |_


[[5,5,5,5,5,5,5,5,5,5,5],[5,10,10,10,10,10,10,10,10,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,25,30,25,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,10,10,10,10,10,10,10,10,5],[5,5,5,5,5,5,5,5,5,5,5]]
  _ _ _ _ _ _ _ _ _  
 |                 | 
 |    _ _ _ _ _    | 
 |   |         |   | 
 |   |    _    |   | 
 |   |   |_|   |   | 
 |   |         |   | 
 |   |_ _ _ _ _|   | 
 |                 | 
 |_ _ _ _ _ _ _ _ _| 

[[35,32,29,26,25,25,25,26,29,32,35],[32,28,25,22,20,20,20,22,25,28,32],[29,25,21,18,15,15,15,18,21,25,29],[26,22,18,14,11,10,11,14,18,22,26],[25,20,15,11,7,5,7,11,15,20,25],[25,20,15,10,5,0,5,10,15,20,25],[25,20,15,11,7,5,7,11,15,20,25],[26,22,18,14,11,10,11,14,18,22,26],[29,25,21,18,15,15,15,18,21,25,29],[32,28,25,22,20,20,20,22,25,28,32],[35,32,29,26,25,25,25,26,29,32,35]]
  _|             |_  
_|    _ _ _ _ _    |_
    _|         |_    
   |    _ _ _    |   
   |   |     |   |   
   |   |     |   |   
   |   |_ _ _|   |   
   |_           _|   
_    |_ _ _ _ _|    _
 |_               _| 
   |             |  

1
Я навіть не починаю це читати, перш ніж зрозуміти, наскільки це буде круто
Крістофер

Відповіді:


6

Perl 6 , 135 байт (131 символів)

{my$n="_";sub w{$^a.chop-$^b.chop??$n!!" "};my&q={|.[1..*],.tail};(($_ «[&w]».&q) ZZ~{$n="|";$_ «[&w]».map(*.&q)}()).map:{say |$_}}

Спробуйте в Інтернеті!

Трохи незворушений:

{
    my $n = "_";
    sub w { $^a.chop - $^b.chop ?? $n !! " "};
    my &q = {|.[1..*],.tail};
    (
        ($_ «[&w]».&q)
        ZZ~
        {$n="|";$_ «[&w]».map(*.&q)}()
    ).map:{say |$_}
}

Пояснення : Спочатку ми визначаємо змінну $n(рядок 2) та функцію w(рядок 3). Ця функція повертає пробіл, якщо два його аргументи знаходяться в одному і тому ж «елевації», а вміст змінної в $nіншому випадку. Замість того, щоб ділити на 10 та підлогу, ми зловживаємо тим, що ints є Cool(можна розглядати як рядки) і використовуємо chopдля видалення останнього символу (= цифра). Потім ми їх спокійно віднімаємо, змушуючи їх знову в числах :—).

Після цього (рядок 4) ми складаємо функцію, qяка бере список і повертає цей список із вилученим першим елементом та дублюванням останнього елемента.

У наступних 3 рядках ми збираємося зробити ще дві матриці з вхідної матриці: в першому відсутній перший рядок, а в останньому рядку дублюється (це просто .&q- використовуючи .&, ви можете викликати функцію на будь-що, як якщо б це було метод - річ перед крапкою є тоді першим аргументом), в другому - перший стовпчик відсутній, а останній стовпчик - дублюється (це .map(*.&q)).

Спочатку (рядок 4) беремо оригінальну матрицю $_, «накладаємо» її на матрицю «зміщених рядків» і використовуємо функцію wяк двійковий оператор (ось це [&w]) на збіжних елементах. Той кладе _туди, де відповідні елементи знаходяться на різних висотах, а інше. Таким чином ми отримуємо 1/2 результату (лише «перші символи»).

У рядку 6 робимо те ж саме, але спершу переходимо $nна |, і тепер «накладаємо» оригінальну матрицю на матрицю зі зміщеними стовпцями. Результат має |різну і однакову висоту. Це "другі символи".

Тепер ми їх просто поєднуємо. Ми збираємо масиви на блискавку з конкатом (так ...), в результаті чого виходить матриця оригінальної форми, кожний елемент якої є 2 збігаються елементами "напіврозв’язків", об'єднаних. Нарешті, ми просто відображаємо цю матрицю (яка справді є списком списків). Кожен із цих списків згладжений та потім say-ед (надрукований новим рядком). Оскільки sayможна взяти будь-яку кількість аргументів і він роздруковує їх усі без роздільників, роблячи новий рядок лише в кінці, ми отримуємо потрібну картинку на stdout. (І блок повертає список Trues (кожен sayповертає один True), але кого це цікавить.)


+1 заbut who cares
HyperNeutrino

5

Желе ,  25 23  22 байт

-1 байт завдяки милям ( Iвекторизи)

:⁵I;€0ao⁶
Zç”_Zż"ç”|$Y

Повна програма, що друкує результат. Як монадичне посилання воно приймає список списків чисел, висот і повертає списки списків, однак ці "рядки" складаються зі списків двох пар "символів" - якщо це нормально, 1 байт може бути збережений шляхом видалення Y.

Спробуйте в Інтернеті!

Як?

:⁵I;€0ao⁶ - Link 1, assignCharacters (row-wise): list of lists of numbers; character, c
 ⁵        - literal 10
:         - integer division (vectorises)
  I       - incremental differences (vectorises) (zero if the same else non-zero)
     0    - literal 0
   ;€     - concatenate for €ach (rightmost edge of a row has no contour mark)
      a   - logical and (vectorises) with c (replace non-zeros with the contour character)
        ⁶ - literal space character
       o  - logical or (vectorises) (replace the zeros with spaces)

Zç”_Zż"ç”|$Y - Main link: list of lists of numbers, contours
Z            - transpose the input (get the columns)
  ”_         - literal underscore character, '_'
 ç           - call the last link (1) as a dyad with '_'
    Z        - transpose the result
          $  - last two links as a monad:
        ”|   -   literal pipe character, '|'
       ç     -   call the last link (1) as a dyad with '|'
      "      - zip with the dyadic operation:
     ż       -   zip (interleave the column-wise characters with the row-wise ones)
           Y - join with newlines
             - implicit print

гр. 3 байти +1, але я спробую перевершити тебе;)
HyperNeutrino

Самостійне рішення - щойно побачив ваше дуже схоже! рятує вас одне ...
Джонатан Аллан

Ви можете зберегти байт, скориставшись кожним підключенням у помічнику :⁵I;€0ao⁶замість основної ланкиZç”_Zż"ç”|$Y
миль

@miles О, вау, це працює? Спасибі! Я уявляв, Iщо не векторизуватись так.
Джонатан Аллан

Так, Iвекторизуються на глибині 1, і обидва, aі oвекторизуються на глибині 0
миль


3

Желе , 24 байти

:⁵IṠ;€0
ZÇZị⁾_ +³Ç¤ị⁾| ¤

Спробуйте в Інтернеті!

Пояснення

:⁵IṠ;€0           Helper Link; get contour data
:                 Floor division by
 ⁵                10
  I               Compute increments
   Ṡ              Sign; ±1 for different values and 0 for same values
    ;             Append
      0           Zero
     €            To each row
ZÇZị⁾_ +³Ç¤ị⁾| ¤  Main Link
Z                 Zip the input (for vertical contours _)
 Ç                Get the contour data
  Z               Zip the data (because it's zipped from the first Z)
   ị              Index into the string
    ⁾_            "_ "
       +          Add (vectorizing twice) to
        ³ ¤    ¤  Nilad starting from (input)
         Ç        Get contour data (horizontal contours |)
           ị      Index into the string
            ⁾|    "| "

-2 байти завдяки Джонатану Аллану


Ваше рішення насправді може покінчити з Y- воно поверне список списків символів, що, на мою думку, добре (тоді як у мого є пари всередині "рядків").
Джонатан Аллан

@JonathanAllan о так, правда ... дякую!
HyperNeutrino

2

Python 2 , 226 байт

l=[[j/10for j in i]for i in input()]
for i,j in enumerate(l[:-1]):print''.join('_ '[h==l[i+1][g]]+'| '[h==j[g+1]]for g,h in enumerate(j[:-1]))+'_ '[j[-1]==l[i+1][-1]]
print''.join(' '+'| '[i==j]for i,j in zip(l[-1],l[-1][1:]))

Спробуйте в Інтернеті!

Так, це було глуздом для розробки логіки. Зараз я бачу, як Hyper Neutrino ніндзя сказав мені коротшу відповідь, але я витратив надто багато роботи над цим, щоб не опублікувати його. : P

Крім того, можна сказати, що це дивовижний спосіб зробити ASCII мистецтвом. Вибачте, поки я заробляю на човні більше таких.


> ninja'd: чувак минуло 45 хвилин
HyperNeutrino

Так, я не дивився на відповіді ...: P
абсолютнолюдський

Ви можете зберегти 4 байти, визначивши змінну для, enumerateа не використовуючи повне ім’я двічі.
Джонатан Фрех

218 байт , видаливши перший enumerate(останній день, мені довелося видалити деякі входи, щоб мати змогу пов’язати це тут)
Феліпе Нарді Батіста

2

J, 58 байт

f=.{~0==/@]
[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10

Спробуйте в Інтернеті!

Анонімна функція, яка приймає матрицю і виводить контури.

Тут багато місця для вдосконалення. Я не встиг спробувати всі тестові справи, тому повідомте мені, чи є проблеми. Постараємося більше грати в гольф і поясню пізніше.

(Швидке) Пояснення

Допоміжна функція: індексується на рядок довжиною 2 на основі того, чи є перший елемент масиву довжиною 2 рівним другому. Якщо вона дорівнює, вона індексується в нульовий елемент, якщо вона нерівна, вона індексується в перший. Масив довжиною 1 завжди індексує нульовий елемент рядка.

f=.{~0==/@]

Основна функція

[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10

1:+<.@%&10 підлоги кожен елемент ділить на 10 і додає 1 (тому ми ніколи не отримаємо 0 - це важливо для функції помічника).

2 2((' _'f{."1),' |'f{.);.3розрізає матрицю на 2 х 2 сегменти, якщо вона може (інакше вона дасть сегмент 2 х 1, 1 х 2 або 1 х 1 біля країв) і застосовує функцію, яка використовує fдля порівняння верхнього лівого елемента з верхнім праворуч і лівий верхній елемент ліворуч знизу.

(,/"2)вирівнює результат у потрібну форму. Мені справді здається, що я маю змогу уникнути необхідності користуватися цим (і багатьма іншими речами, але я відступаю).



2

JavaScript (ES6), 120 118 байт

a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>((a[i+1]||0)[j]-c?'_':' ')+(b[j+1]-c?'|':' ')).join``).join`\n`

Де \nпредставляє буквальний символ нового рядка. Редагувати: Збережено 2 байти завдяки @ Bálint.

f=
a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>((a[i+1]||0)[j]-c?'_':' ')+(b[j+1]-c?'|':' ')).join``).join`
`
;[
[[5,20],[3,6]]
,
[[1,5,8,9],[3,11,13,8],[7,14,10,9],[4,8,7,6]]
,
[[0,10,20,30,40,50,60,70,80,90],[0,0,10,10,20,20,30,30,40,40],[0,0,0,10,10,10,20,20,20,30],[0,0,0,0,10,10,10,10,20,20],[0,0,0,0,0,10,10,10,10,10],[0,0,0,0,0,0,10,10,10,10],[0,0,0,0,0,0,0,10,10,10],[0,0,0,0,0,0,0,0,10,10],[0,0,0,0,0,0,0,0,0,10],[0,0,0,0,0,0,0,0,0,0]]
,
[[5,5,5,5,5,5,5,5,5,5,5],[5,10,10,10,10,10,10,10,10,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,25,30,25,20,15,10,5],[5,10,15,20,25,25,25,20,15,10,5],[5,10,15,20,20,20,20,20,15,10,5],[5,10,15,15,15,15,15,15,15,10,5],[5,10,10,10,10,10,10,10,10,10,5],[5,5,5,5,5,5,5,5,5,5,5]]
,
[[35,32,29,26,25,25,25,26,29,32,35],[32,28,25,22,20,20,20,22,25,28,32],[29,25,21,18,15,15,15,18,21,25,29],[26,22,18,14,11,10,11,14,18,22,26],[25,20,15,11,7,5,7,11,15,20,25],[25,20,15,10,5,0,5,10,15,20,25],[25,20,15,11,7,5,7,11,15,20,25],[26,22,18,14,11,10,11,14,18,22,26],[29,25,21,18,15,15,15,18,21,25,29],[32,28,25,22,20,20,20,22,25,28,32],[35,32,29,26,25,25,25,26,29,32,35]]
].forEach(a=>document.write(['<pre>','</pre>'].join(f(a))));


Ви можете повернути (a[i] || [])[j]конструкції до(a[i] || 0)[j]
Bálint

Також в останньому join`\n`ви можете зняти \nдеталь і замінити її фактичною новою
лінією

114 байт:a=>a.map(b=>b.map(c=>c/10|0)).map((b,i,a)=>b.map((c,j)=>" _"[(a[i+1]||0)[j]-c&1]+" |"[b[j+1]-c&1]).join``).join`<new line here>`
Bálint

@ Bálint Bah, я забуваю робити цю \nчастину; Я тестуюсь на REPL, щоб буквальні нові рядки заважали.
Ніл

@ Bálint Але ваша остання пропозиція не відповідає оригінальному прикладу, який я додав до списку результатів.
Ніл

1

Протон , 202 байти

R=(L=len)+range
k=[map((//)&10,r)for r:eval(input())]
d=(x,y,X,Y)=>X>=L(k)or Y>=L(k[X])or k[x][y]==k[X][Y]
print('\n'.join(map(''.join,[['_ '[d(x,y,x+1,y)]+'| '[d(x,y,x,y+1)]for y:R(k[x])]for x:R(k)])))

Спробуйте в Інтернеті!

-2 байти завдяки Джонатану Фреху
-15 байт, перейшовши на Протон замість Python 2


Ви можете зберегти два байта, замінивши lenз Lі визначення L=len;.
Джонатан Фрех

1

Java 8, 200 170 169 байт

a->{String r="";for(int l=a.length,i=0,j;i<l;i++,r+="\n")for(j=0;j<l;r+=(i>l-2||a[i][j]/10==a[i+1][j]/10?" ":"_")+(j++>l-2||a[i][j-1]/10==a[i][j]/10?" ":"|"));return r;}

Пояснення:

Спробуйте тут.

Зауважте, що ціле ділення в Java автоматично перепадає.

a->{                   // Method with 2D int-array as parameter and String return-type
  String r="";         //  Result-String
  for(int l=a.length,  //  Length of the input array
      i=0,j;           //  Index integers
      i<l;i++,         //  Loop (1) over the rows of the input array
          r+="\n")     //  and append a new-line to the result after every iteration
    for(j=0;j<l;       //   Inner loop (2) over the columns of a row
      r+=              //    Append the String with:
         (i>l-2        //      If it's the last row,
         ||a[i][j]/10==a[i+1][j]/10?
                       //      or the current and next rows are equal floored/10:
          " "          //       Use a space
         :             //      Else:
          "_")         //       Use a "_"
        +              //     Plus
         (j++>l-2      //      If it's the last column in the row,
         ||a[i][j-1]/10==a[i][j]/10?
                       //      or the current and next columns are equal floored/10:
          " "          //       Use a space
         :             //      Else:
          "|")         //       Use "|"
    );                 //   End of column loop (2)
                       //  End of row-loop (1) (implicit / single-line body)
  return r;            //  Return the result-String
}                      // End of method

1

R, 159 байт

f=function(m){M=m%/%10;a=cbind(0,t(apply(M,1,diff)));b=rbind(apply(M,2,diff),0);a[!!a]="|";b[!!b]="_";M[]=gsub("0"," ",paste0(a,b));write(t(M),"",ncol(m),,"")}

З новими рядками та відступами:

f=function(m){
    M=m%/%10
    a=cbind(0,t(apply(M,1,diff))) #row-wise difference
    b=rbind(apply(M,2,diff),0) #column-wise difference
    a[!!a]="|"
    b[!!b]="_"
    M[]=gsub("0"," ",paste0(a,b)) # M[] is a trick to force the result to have the same structure as M
    write(t(M),"",ncol(m),,"")
    }

Чи ціле поділ матриці вимірює різницеві та стовпчикові різниці, а коли не нульові замінюють на відповідно |і _відповідно, то вставляє як (безболісно, ​​завдяки векторизації R), так і вихід.

Тестові приклади:

> m=matrix(c(0,10,20,30,40,50,60,70,80,90,0,0,10,10,20,20,30,30,40,40,0,0,0,10,10,10,20,20,20,30,0,0,0,0,10,10,10,10,20,20,0,0,0,0,0,10,10,10,10,10,0,0,0,0,0,0,10,10,10,10,0,0,0,0,0,0,0,10,10,10,0,0,0,0,0,0,0,0,10,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0),byrow=T,ncol=10)
> f(m)
  |_|_|_|_|_|_|_|_|_
    |_  |_ _|_ _|_ _
      |_    |_ _  |_
        |_      |_ _
          |_        
            |_      
              |_    
                |_  
                  |_

> m=matrix(c(5,5,5,5,5,5,5,5,5,5,5,5,10,10,10,10,10,10,10,10,10,5,5,10,15,15,15,15,15,15,15,10,5,5,10,15,20,20,20,20,20,15,10,5,5,10,15,20,25,25,25,20,15,10,5,5,10,15,20,25,30,25,20,15,10,5,5,10,15,20,25,25,25,20,15,10,5,5,10,15,20,20,20,20,20,15,10,5,5,10,15,15,15,15,15,15,15,10,5,5,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,5,5),byrow=T,ncol=11)
> f(m)
   _ _ _ _ _ _ _ _ _  
  |                 | 
  |    _ _ _ _ _    | 
  |   |         |   | 
  |   |    _    |   | 
  |   |   |_|   |   | 
  |   |         |   | 
  |   |_ _ _ _ _|   | 
  |                 | 
  |_ _ _ _ _ _ _ _ _| 

0

Perl 5 , 130 126 байт

124 байти коду + 2 для -ap прапорів

push@a,[map 0|$_/10,@F]}{map{say map{($a[$r+1][$c]-$_&&$r<$#a?'_':$").($a[$r][++$c]-$_&&$c<@{$a[0]}?'|':$")}@$_;$c=0;$r++}@a

Спробуйте в Інтернеті!

Формат введення - це 2-D сітка пробілів, розділених пробілами.

Пояснення

Це з попередньої ітерації коду.

push@a,[map 0|$_/10,@F]     # read the input, divide it by 10, and store it in a 2-D array
}{                          # end the implicit while loop and start the final block
map{                        # repeat this for each line
  $_=($a[$r+1][$c]-$_&&$r<$#a?'_':$")       # set appropriate characters to output based
     .($a[$r][++$c]-$_&&$c<@{$a[0]}?'|':$") # on the given rules
  for@$_;                                   # repeat for each number on the line
  $c=0;$r++;                         # setup row and column counters for next iteration
  say@$_                             # output this line
}@a
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.