Нарисуй мои контуры


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 и пол, мы злоупотребляем тем, чтоCool (можно рассматривать как строки), и используемchop для удаления последнего символа (= цифра). Затем мы спокойно вычитаем их, снова превращая их в числа :—).

После этого (строка 4) составим функцию q которая принимает список и возвращает этот список с удаленным первым элементом и дублированным последним элементом.

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

Сначала (строка 4) мы берем исходную матрицу $_, «накладываем» ее на матрицу «сдвинутых строк» ​​и используем функцию wв качестве бинарного оператора (вот так [&w]) на соответствующих элементах. Тот помещает туда, _где совпадающие элементы находятся на разных отметках, и наоборот. Таким образом, мы получаем ½ результата (только «первые символы»).

В строке 6 мы делаем то же самое, но сначала мы изменяем $nна |, и теперь мы «накладываем» исходную матрицу на матрицу со смещенными столбцами. Результат имеет |разный и на одинаковых отметках. Это «вторые персонажи».

Теперь мы просто объединяем их вместе. Мы заархивируем массивы с помощью конкатата (да ...), в результате чего получается матрица исходной формы, каждый элемент которой представляет собой два совпадающих элемента сцепленных «полурешения». Наконец, мы просто отображаем эту матрицу (которая на самом деле представляет собой список списков). Каждый из этих списков сглаживается, а затем - 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
мили

@ Майлз Ого, это работает? Благодарность! Я предполагал, 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 ниндзя дал мне более короткий ответ, но я потратил слишком много работы, чтобы не опубликовать его. :П

Кроме того, могу ли я просто сказать, что это отличный способ сделать ASCII-арт. Извините, пока я делаю лодку еще больше.


> ninja'd: чувак, это было 45 минут
HyperNeutrino

Да, я не смотрел на ответы ...: P
полностью человек

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

218 байт , удалив первый enumerate(obs, я должен был удалить некоторые входные данные, чтобы иметь возможность связать его здесь)
Фелипе Нарди Батиста,

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 x 2 сегмента, если это возможно (в противном случае она даст 2 x 1, 1 x 2 или 1 x 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>`
Балинт

@ Балинт Бах, я постоянно забываю сделать это \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 байтов, переключившись на Proton вместо 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

Попробуйте онлайн!

Формат ввода - двумерная сетка чисел, разделенных пробелами.

объяснение

Это из предыдущей итерации кода.

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.