Dekode Peta Panas

32

Heatmaps

Pertimbangkan sebuah ruangan persegi panjang, yang langit-langitnya memiliki kamera termal yang mengarah ke bawah. Di dalam ruangan, ada sejumlah sumber panas intensitas 1-9, suhu latar belakang sedang 0. Panas menghilang dari setiap sumber, turun satu unit per langkah (non-diagonal). Misalnya 20x10ruangan

...........1........
....................
...8................
..5...............2.
....................
.1..................
................1...
.................65.
....................
............2.......

berisi 9 sumber panas, dan gradien suhu yang ditunjukkan oleh kamera termal

34565432100100000000
45676543210000000000
56787654321000000110
45676543210000001221
34565432100000012321
23454321000000123432
12343210000001234543
01232100000012345654
00121000000011234543
00010000000121123432

Dalam bentuk grafis ini mungkin terlihat seperti:

peta panas dari 9 sumber

Dari gradien, kita dapat menyimpulkan posisi dan intensitas beberapa sumber panas, tetapi tidak semua. Sebagai contoh, semua 9s selalu dapat disimpulkan, karena mereka memiliki suhu maksimal, dan begitu pula 8dalam hal ini, karena menghasilkan maksimum lokal dalam gradien. The 2dekat perbatasan yang tepat juga dapat disimpulkan, meskipun tidak di maksimum lokal, karena tidak memiliki lain 2sebagai tetangga. The 5s, di sisi lain, tidak disimpulkan, karena panas mereka mungkin juga dihasilkan oleh sumber-sumber yang lebih intens di dekat mereka. The 0s diketahui tidak mengandung sumber panas, tetapi semua ubin lain mungkin berpotensi mengandung satu. Mari kita tunjukkan ubin tidak pasti oleh tanda hubung-, sumber panas tertentu dengan digit yang sesuai, dan ruang kosong tertentu berdasarkan periode .:

---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------

Tugas Anda adalah menghasilkan pola yang disimpulkan ini dari gradien suhu.

Aturan

Anda diberi input sebagai string yang dibatasi oleh baris baru atau pipa vertikal |, mana yang lebih nyaman, dan output harus dari bentuk yang sama. Mungkin ada pembatas trailing di input dan / atau output, tetapi tidak ada yang sebelumnya. Ukuran input dapat bervariasi, tetapi lebar dan tingginya selalu paling tidak 4. Fungsi dan program lengkap dapat diterima. Hitungan byte terendah menang, dan celah standar dilarang.

Kasus Uji Tambahan

Memasukkan:

898778765432100
787667654321100
677656543211210
678765432112321
567654321123210

yang terlihat seperti ini dalam bentuk grafis:

test case 1

Keluaran:

-9---8-------..
-------------..
--------------.
--8---------3--
-----------3--.

Memasukkan:

7898
8787
7676
6565

Keluaran:

--9-
8---
----
----

Memasukkan:

00001
00000
00000
10000

Keluaran:

....1
.....
.....
1....
Zgarb
sumber
1
Apakah Anda keberatan jika saya menambahkan 2 grafik peta panas ke pertanyaan Anda jika Anda pikir mereka menambah nilai? Mereka hanya percobaan 2 menit.
Logic Knight
@CarpetPython Tentu, silakan. Mereka terlihat sangat baik padaku. Anda juga dapat menambahkan "Courtesy of CarpetPython" untuk memberi diri Anda kredit. ;)
Zgarb
2
Selesai Tidak perlu kredit, tapi saya pikir tidak sopan untuk tidak bertanya sebelum mengedit.
Logic Knight
Mengapa tidak mengizinkan input sebagai array 2 dimensi alih-alih string?
feersum
@feersum umumnya metode input konsisten.
Pengoptimal

Jawaban:

10

CJam, 73 69 62 55 byte

PEMBARUAN : Algoritma baru. Ruang lingkup yang lebih pendek dan lebih banyak untuk perbaikan

qN/5ff*{{[{_@_@<{I'0t}*\}*]W%}%z}4fI{):X-'-X~X'.??}f%N*

Bagaimana itu bekerja

Logikanya mirip dengan algoritma di bawah ini, tetapi di sini saya tidak memeriksa semua 4 tetangga dalam satu iterasi tunggal. Sebagai gantinya, saya menggunakan pendekatan yang lebih kecil untuk beralih melalui semua baris dan kolom di kedua arah. Berikut langkah-langkahnya:

  • Konversi setiap karakter menjadi set 5. Yang pertama akan dimodifikasi untuk mengetahui apakah mereka lebih besar dari sel yang berdekatan di baris saat iterasi. Yang terakhir adalah untuk tujuan perbandingan.
  • Iterasi di setiap baris dan kurangi di setiap baris. Sambil mengurangi, saya memiliki dua string 5 karakter. Saya tahu jenis iterasi yang mana [0 untuk baris normal, 1 kolom terbalik, 2 untuk baris terbalik dan 3 untuk kolom normal] Saya memperbarui karakter ke- i dalam string 5 karakter pertama dan menjadikannya 0 jika lebih kecil dari yang kedua .
  • Setelah semua 4 iterasi, jika semua 5 karakter sama dan tidak nol, itu adalah maksimum lokal. Saya memetakan melalui semua 5 karakter string dan mengubahnya menjadi satu digit, .atau -.

Berikut ini contoh yang dijalankan pada input kecil:

7898
8787
7676
6565

Setelah langkah pertama:

["77777" "88888" "99999" "88888"
 "88888" "77777" "88888" "77777"
 "77777" "66666" "77777" "66666"
 "66666" "55555" "66666" "55555"]

Setelah langkah kedua:

["00777" "08888" "99999" "88088"
 "88888" "07007" "88808" "77007"
 "77707" "06006" "77707" "66006"
 "66606" "05005" "66606" "55005"]

Setelah pemetaan terakhir ke karakter tunggal, hasil akhir:

--9-
8---
----
----

Penjelasan Kode :

qN/5ff*                         "Split the input on new line and convert each character";
                                "to string of 5 of those characters.";
{{[{             }*]W%}%z}4fI   "This code block runs 4 times. In each iteration, it";
                                "maps over each row/column and then for each of them,";
                                "It reduce over all elements of the row/column";
                                "Using combination of W% and z ensures that both rows and";
                                "columns are covered and in both directions while reducing";
    _@_@                        "Take a copy of last two elements while reducing over";
        <                       "If the last element is bigger than second last:";
         {I'0t}*\               "Convert the Ith character of the 5 char string of"
                                "second last element to 0";
                                "We don't have to compare Ith character of last two 5 char";
                                "string as the smaller one will be having more leading";
                                "0 anyways. This saves 4 bytes while comparing elements";
{):X-'-X~X'.??}f%N*             "This part of code converts the 5 char back to single char";
 ):X                            "Remove the last character and store in X. This last char";
                                "was not touched in the prev. loop, so is the original char";
    -                           "Subtract X from remaining 4 char. If string is not empty";
                                "then it means that it was not all same characters";
                                "In other words, this character was smaller then neighbors";
     '-      ?                  "If non-empty, then replace with - else ...";
       X~X'.?                   "if int(X) is zero, put . else put X";
               f%N*             "The mapping code block was run for each row and then";
                                "The rows are joined by newline.";

Coba di sini


Pendekatan yang lebih tua

qN/~_,):L0s*]0s*:Q_,{QI=:A[W1LL~)]If+Qf=$W=<'-A?A~\'.?I\t}fIL/W<Wf<N*

Bagaimana itu bekerja

Logikanya sederhana, iterasi melalui grid dan lihat apakah nilai saat ini lebih besar atau sama dengan empat tetangga yang tersisa - atas, bawah, kiri dan kanan. Kemudian mentransformasikan nilai saat ini berdasarkan aturan di atas dan jika nilainya sama dengan 0, buat "." .

Penjelasan Kode

qN/~_,):L0s*]0s*:Q         "This part of code pads the grid with 0s";
qN/~                       "Read the input, split on new lines and unwrap the arrays";
    _,):L                  "Copy the last row, taken length, increment and store in L";
         0s*               "Get L length 0 string";
            ]0s*           "Wrap everything in an array and join the rows by 0";
                :Q         "Store this final single string in Q";

_,{        ...      }fI    "Copy Q and take length. For I in 0..length, execute block";
   QI=:A                   "Get the I'th element from Q and store in A";
   [WiLL~)]If+             "This creates indexes of all 4 neighboring cells to the Ith cell";
              Qf=          "Get all 4 values on the above 4 indexes";
                 $W=       "Sort and get the maximum value";
<'-A?                      "If the current value is not the largest, convert it to -";
     A~\'.?                "If current value is 0, convert it to .";
           I\t             "Update the current value back in the string";
{ ... }fIL/                "After the loop, split the resulting string into chunks of L";
           W<Wf<           "Remove last row and last column";
                N*         "Join by new line and auto print";

Cobalah online di sini

Pengoptimal
sumber
5
Saya harus mengatakan, saya jarang mendengar "terlalu lama" ketika menjelaskan kode CJam.
Alex A.
6

JavaScript (ES6) 99

F=h=>[...h].map((c,i)=>[o=~h.search('\n'),-o,1,-1].some(d=>h[d+i]>c)&c>0?'-':c=='0'?'.':c).join('')

Uji di Firefox / konsol FireBug

console.log(F('\
34565432100100000000\n\
45676543210000000000\n\
56787654321000000110\n\
45676543210000001221\n\
34565432100000012321\n\
23454321000000123432\n\
12343210000001234543\n\
01232100000012345654\n\
00121000000011234543\n\
00010000000121123432\n'),'\n\n',
F('\
898778765432100\n\
787667654321100\n\
677656543211210\n\
678765432112321\n\
567654321123210\n'), '\n\n',
F('7898\n8787\n7676\n6565\n'))

Keluaran

---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------


-9---8-------..
-------------..
--------------.
--8---------3--
-----------3--.


--9-
8---
----
----
edc65
sumber
4

Python 2: 154 byte

b=input()
l=b.index('\n')+1
print''.join(('\n.'+('-'+v)[all([v>=b[j]for j in i-l,i-1,i+l,i+1if 0<=j<len(b)])])[('\n0'+v).index(v)]for i,v in enumerate(b))

Masukan harus dalam bentuk "00001\n00000\n00000\n10000".

Mengubah string ke matriks 2D cukup panjang dalam Python. Jadi saya menyimpan format string asli. Saya menyebutkan input, iadalah indeks, vadalah char (Akhirnya menghitung byte yang disimpan dalam solusi golf !!). Untuk setiap pasangan (i,v)saya menghitung karakter output yang benar, dan bergabung dengan mereka. Bagaimana cara memilih karakter keluaran yang benar? Jika v == '\n', output char adalah \n, itu v == '0', daripada char output '.'. Kalau tidak, saya menguji 4 tetangga v, yang b[i-b.index('\n')-1](atas), b[i-1](kiri, b[i+1](kanan) dan b[i+b.index('\n')+1](bawah), jika mereka <= vdan memilih char '-'atauv. Di sini saya membandingkan karakter bukan angka, tetapi berfungsi cukup baik, karena nilai ascii berada dalam urutan yang benar. Juga tidak ada masalah, jika b[i-1]atau b[i+1]sama '\n', karena ord('\n') = 10.

Pyth: 61 58

JhxQbVQK@QN~k@++b\.?\-f&&gT0<TlQ<K@QT[tNhN-NJ+NJ)Kx+b\0K)k

Lebih atau kurang terjemahan skrip Python. Cukup jelek ;-)

Cobalah online: Pyth Compiler / Executor Format input yang sama dengan solusi Python.

JhxQb      Q = input()
  xQb      Q.index('\n')
 h         +1
J          store in J

VQK@QN~k.....)k   k is initialized as empty string
VQ           )    for N in [0, 1, 2, ..., len(Q)-1]:
  K@QN                K = Q[n]
      ~k              k += ... (a char, computed in the next paragraph)
             )    end for
              k   print k

@...x+b\0K   ... is a char of len 3 (is constructed below)
     +b\0    the string "\n0"
    x    K   find Q[d] in this string and return index, if not found -1
@...         lookup in string at the computed position (this is done mod 3 automatically!)

++b\.?\-f&&gT0<TlQ<K@QT[tNhN-NJ+NJ)K   not to the string
                       [tNhN-NJ+NJ)    the list [d-1, d+1, d-J, d+j]
        f                              filter the list for indices T which
           gT0                            T >= 0
          &                               and
              <TlQ                        T < len(Q)
         &                                and
                  <K@QT                   Q[d] < Q[T]
     ?\-                           K   use "-" if len(filter) > 0 else Q[d]
                                       this creates the third char
++b\.                                  "\n" + "." + third char
Jakube
sumber
4

Perl, 77, 75, 72 70

Trik pencocokan regex 2d standar.

#!perl -p0
/
/;$x="(.{@-})?";y/0/./while s/$.$x\K$"|$"(?=$x$.)/-/s||($"=$.++)<9

Contoh:

$ perl heat.pl <in.txt
---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------

Coba di sini

nutki
sumber
3

Java, 307 , 304 , 303 , 299 298

Ini pasti tantangan "sempurna" untuk beberapa codegolf Java :)

class M{public static void main(String[]a){int c=a[0].indexOf('|'),i=c,d,v;char[]r=a[0].replace("|","").toCharArray(),m=new char[(v=r.length+c)+c];for(;i<v;){m[i]=r[i++-c];}for(i=c;i<v;i++){a[0]=i%c<1?"\n":"";d=m[i];System.out.print(a[0]+(d<49?'.':m[i-c]>d|m[i+c]>d|m[i-1]>d|m[i+1]>d?'-':m[i]));}}}

Input (metode pipa | |):

34565432100100000000|45676543210000000000|56787654321000000110|45676543210000001221|34565432100000012321|23454321000000123432|12343210000001234543|01232100000012345654|00121000000011234543|00010000000121123432

Keluaran:

---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------
Rolf ツ
sumber
1
Ini bisa 288 jika Anda menghapus ruang di char[]r=a[0].replace("|", <--here"").toCharArray().
bcsb1001
1
Tidak menemukan yang itu, terima kasih! Nah ini membuat 298
Rolf ツ
2

APL, 92

('.-',⎕D)[1+(M≠0)+M{(1+⍺)×0≠⍺∧M[J/⍨Z∊⍨J←⍵∘+¨(⌽¨,+)(-,+)⊂0 1]∧.≤⍺}¨Z←⍳⍴M←↑{×⍴⍵:(⊂⍎¨⍵),∇⍞⋄⍬}⍞]

Contoh:

       ('.-',⎕D)[1+(M≠0)+M{(1+⍺)×0≠⍺∧M[J/⍨Z∊⍨J←⍵∘+¨(⌽¨,+)(-,+)⊂0 1]∧.≤⍺}¨Z←⍳⍴M←↑{×⍴⍵:(⊂⍎¨⍵),∇⍞⋄⍬}⍞]
34565432100100000000
45676543210000000000
56787654321000000110
45676543210000001221
34565432100000012321
23454321000000123432
12343210000001234543
01232100000012345654
00121000000011234543
00010000000121123432

---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------
marinus
sumber
Program APL terlama yang pernah saya lihat. Anda mungkin ingin mencatat bahwa ini bukan APL standar karena menggunakan dfns.
FUZxxl
2

Ruby 140

f=->s{
r=s.dup
l=s.index(?\n)+1
(0...s.size).map{|i|
s[i]<?0||r[i]=r[i]<?1??.:[i-1,i+1,i-l,i+l].map{|n|n<0??0:s[n]||?0}.max>r[i]??-:s[i]}
r}

Tidak ada yang spesial; hanya beralih melalui peta dan bandingkan nilai saat ini dengan nilai empat tetangga.

Jalankan secara online dengan tes: http://ideone.com/AQkOSY

Cristian Lupascu
sumber
1

R, 223

Tentang yang terbaik yang bisa saya pikirkan saat ini. Berurusan dengan tali itu cukup mahal. Saya pikir ada ruang untuk perbaikan, tetapi tidak bisa melihatnya saat ini

s=strsplit;a=c(m<-do.call(rbind,s(s(scan(w="c"),'|',T)[[1]],'')));w=(d<-dim(m))[1];n=c(-1,1,-w,w);cat(t(array(sapply(seq(a),function(x)if(a[x]>0)if(any(a[(n+x)[which(n+x>0)]]>a[x]))'-'else a[x]else'.'),d)),fill=d[2],sep='')

Hasil tes

> s=strsplit;a=c(m<-do.call(rbind,s(s(scan(w="c"),'|',T)[[1]],'')));w=(d<-dim(m))[1];n=c(-1,1,-w,w);cat(t(array(sapply(seq(a),function(x)if(a[x]>0)if(any(a[(n+x)[which(n+x>0)]]>a[x]))'-'else a[x]else'.'),d)),fill=d[2],sep='')
1: 898778765432100|787667654321100|677656543211210|678765432112321|567654321123210
2: 
Read 1 item
-9---8-------..
-------------..
--------------.
--8---------3--
-----------3--.
> s=strsplit;a=c(m<-do.call(rbind,s(s(scan(w="c"),'|',T)[[1]],'')));w=(d<-dim(m))[1];n=c(-1,1,-w,w);cat(t(array(sapply(seq(a),function(x)if(a[x]>0)if(any(a[(n+x)[which(n+x>0)]]>a[x]))'-'else a[x]else'.'),d)),fill=d[2],sep='')
1: 34565432100100000000|45676543210000000000|56787654321000000110|45676543210000001221|34565432100000012321|23454321000000123432|12343210000001234543|01232100000012345654|00121000000011234543|00010000000121123432
2: 
Read 1 item
---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------
> 
MickyT
sumber
1

J - 69 byte

[:u:45+[:(+2 0 3{~"#1+*)@((]*]=(0,(,-)1 0,:0 1)>./@:|.])-0=])"."0;._2

Contoh:

   ([:u:45+[:(+2 0 3{~"#1+*)@((]*]=(0,(,-)1 0,:0 1)>./@:|.])-0=])"."0;._2) (0 : 0)
34565432100100000000
45676543210000000000
56787654321000000110
45676543210000001221
34565432100000012321
23454321000000123432
12343210000001234543
01232100000012345654
00121000000011234543
00010000000121123432
)
---------..1........
----------..........
---8-------......--.
----------......--2-
---------......-----
--------......------
-------......-------
.-----......-----6--
..---.......--------
...-.......-2-------
   ([:u:45+[:(+2 0 3{~"#1+*)@((]*]=(0,(,-)1 0,:0 1)>./@:|.])-0=])"."0;._2) (0 : 0)
898778765432100
787667654321100
677656543211210
678765432112321
567654321123210
)
-9---8-------..
-------------..
--------------.
--8---------3--
-----------3--.

PS: (0 : 0)adalah cara standar J menentukan string. Anda mungkin juga menggunakan |string yang dibatasi (dengan trailing |).

jpjacobs
sumber
1

Excel VBA - 426

Ini akan menjadi kesempatan langka bahwa VBA memenangkan permainan golf kode apa pun, tetapi karena ini yang paling saya gunakan, menyenangkan untuk bermain-main dengannya. Baris pertama adalah kasus tepi yang membuat ini lebih lama dari yang seharusnya.

Sub m(a)
    b = InStr(a, "|")
    For i = 1 To Len(a)
        t = Mid(a, i, 1)
        Select Case t
            Case "|"
                r = r & "|"
            Case 0
                r = r & "."
            Case Else
                On Error Resume Next
                x = Mid(a, i - 1, 1)
                y = Mid(a, i + 1, 1)
                Z = Mid(a, i + b, 1)
                If i < b Then
                    If t < x Or t < y Or t < Z Then
                        r = r & "-"
                    Else
                        r = r & t
                    End If
                Else
                    If t < x Or t < y Or t < Z Or t < Mid(a, i - b, 1) Then
                        r = r & "-"
                    Else
                        r = r & t
                    End If
                End If
        End Select
    Next
    MsgBox r
End Sub

Hitungannya tidak termasuk spasi spasi awal.

Saya bermain-main dengan ide mengirim input ke selembar dan bekerja dari sana, tapi saya pikir perulangan string yang lewat karakter-demi-karakter menyimpan kode.

Panggilan dari Jendela Segera:

m "34565432100100000000|45676543210000000000|56787654321000000110|45676543210000001221|34565432100000012321|23454321000000123432|12343210000001234543|01232100000012345654|00121000000011234543|00010000000121123432"

Output (dalam Window):

---------..1........|----------..........|---8-------......--.|----------......--2-|---------......-----|--------......------|-------......-------|.-----......-----6--|..---.......--------|...-.......-2-------
phrebh
sumber
1

Perl - 226

sub f{for(split'
',$_[0]){chomp;push@r,r($_);}for(t(@r)){push@y,r($_)=~s/0/./gr}$,=$/;say t(@y);}sub r{$_[0]=~s/(?<=(.))?(.)(?=(.))?/$1<=$2&&$3<=$2?$2:$2eq'0'?0:"-"/ger;}sub t{@q=();for(@_){for(split//){$q[$i++].=$_;}$i=0;}@q}

Anda dapat mencobanya di ideone . Jika ada yang tertarik pada penjelasan, beri tahu saya.

hmatt1
sumber
Saya pikir Anda memiliki 226 karakter, bukan 227.
Cristian Lupascu
@ w0Jika Anda benar, baris baru dihitung untuk 2 karena saya di Windows.
hmatt1
1

Haskell - 193

z='0'
r=repeat z
g s=zipWith3(\u t d->zip3(zip(z:t)u)t$zip(tail t++[z])d)(r:s)s$tail s++[r]
f=unlines.map(map(\((l,u),t,(r,d))->case()of _|t==z->'.'|maximum[u,l,t,r,d]==t->t|0<1->'-')).g.lines

fadalah fungsi yang mengambil string dalam bentuk 0001\n0000\n0000\n1000dan mengembalikan string yang diperlukan.

g adalah fungsi yang mengambil daftar daftar karakter dan mengembalikan daftar daftar ((kiri, atas), ini, (kanan, bawah)).

Jmac
sumber