Isı Haritasını Çözme


32

Heatmaps

Tavanında aşağıya doğru bakan termal bir kameranın olduğu dikdörtgen bir oda düşünün. Odada, arkaplan sıcaklığı olan bazı ısı yoğunluk kaynakları vardır . Isı, her kaynaktan (çapraz olmayan) adım başına bir birim düşerek dağılır. Örneğin, oda1-9020x10

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

9 ısı kaynağı içerir ve termal kamera tarafından gösterilen sıcaklık gradyanı

34565432100100000000
45676543210000000000
56787654321000000110
45676543210000001221
34565432100000012321
23454321000000123432
12343210000001234543
01232100000012345654
00121000000011234543
00010000000121123432

Grafik biçiminde bu gibi görünebilir:

9 kaynağın ısı haritası

Gradyandan, bazı ısı kaynaklarının konumlarını ve yoğunluklarını çıkartabiliriz, hepsini değil. Örneğin, her 9zaman en fazla sıcaklığa sahip olduklarından, her zaman 8sonuç çıkarılabilir ve bu durumda degradede yerel bir maksimum ürettiği için olabilir. 2Yakın sağ sınır da başka olmadığı için, yerel bir maksimumda olmadığı halde, anlaşılabilir 2bir komşu olarak. 5Onların ısı yanı onlara yakın daha yoğun kaynaklar tarafından üretilecek olabileceğinden ler, diğer taraftan, anlaşılmaktadır değildir. 0S ısı kaynakları ihtiva bilinmektedir, ancak tüm diğer fayans olabilir , potansiyel olarak bir içermektedir. Belirsiz fayansları tire ile gösterelim-, karşılık gelen rakamlarla belirli ısı kaynakları ve dönemlere göre belirli boş alanlar .:

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

Göreviniz, bu çıkarılan deseni sıcaklık gradyanından üretmek olacaktır.

kurallar

Girdi |, hangisi daha uygunsa, size yeni hatlar veya dikey borular tarafından sınırlandırılmış bir dize olarak verilir. Çıktı aynı biçimde olacaktır. Girişte ve / veya çıktıda iz bırakan bir sınırlayıcı olabilir, ancak bunlardan birincisi olmayabilir. Girişin boyutu değişebilir, ancak genişliği ve yüksekliği daima en azdır 4. Hem fonksiyonlar hem de tam programlar kabul edilebilir. En düşük bayt sayısı kazanır ve standart boşluklar yasaktır.

Ek Test Durumları

Giriş:

898778765432100
787667654321100
677656543211210
678765432112321
567654321123210

grafiksel olarak buna benzeyen:

test durumu 1

Çıktı:

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

Giriş:

7898
8787
7676
6565

Çıktı:

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

Giriş:

00001
00000
00000
10000

Çıktı:

....1
.....
.....
1....

1
Sorunuza 2 ısı haritası grafiği eklesem sorun olur mu? Onlar sadece 2 dakikalık bir deney.
Mantık Şövalye

@CarpetPython Tabii, devam et. Bana çok iyi görünüyorlar. Kendinize kredi vermek için bir "CarpetPython İzniyle" de ekleyebilirsiniz. ;)
Zgarb

2
Bitti. Kredi gerekli değil, ancak düzenlemeden önce sormamanın kaba olacağını düşündüm.
Mantık Şövalye

Girişe neden bir dize yerine 2 boyutlu bir dizi olarak izin vermiyor?
15’deki feersum

@ feersum genellikle giriş yöntemleri tutarlıdır.
Doktor,

Yanıtlar:


10

CJam, 73 69 62 55 bayt

GÜNCELLEME : Yeni algoritma. İyileştirme için daha kısa ve daha fazla kapsam

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

Nasıl çalışır

Mantık, aşağıdaki algoritmaya benzer, ancak burada tek bir yinelemede 4 komşuyu da kontrol edemiyorum. Bunun yerine, her iki yönde de tüm satır ve sütunlarda yineleme yapmak için daha küçük bir yaklaşım kullanıyorum. İşte ilgili adımlar:

  • Her karakteri 5'lik kümelere dönüştürün. İlk 4, yinelenirken satırdaki bitişik hücreden daha büyük olup olmadığını söylemek için değiştirilecektir. Sonuncusu karşılaştırma amaçlıdır.
  • Her satırda tekrarlayın ve her satırda azaltın. Küçülürken iki tane 5 karakterli dizgem var. Ben tür yineleme ne olduğunu biliyoruz [Normal satırlar için 0, 1 sütun, ters satırlar için 2 ters ve sütunlar için 3 Normal] Ben güncellemek inci ilk 5 karakter dizesinde karakter ve ikinci küçükse Durum 0 .
  • 4 yinelemenin ardından, 5 karakterin tümü aynıysa ve sıfır değilse, bu yerel maksimum değerdir. Tüm 5 karakter dizeleri ile harita ve ya tek haneye onları dönüştürmek, .ya da -.

İşte küçük bir girişte çalıştırılacak bir örnek:

7898
8787
7676
6565

İlk adımdan sonra:

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

İkinci adımdan sonra:

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

Tek karaktere son eşlemeden sonra, son çıktı:

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

Kod Açıklaması :

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.";

Burada dene


Daha eski yaklaşım

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

Nasıl çalışır

Mantık basit, ızgara boyunca yineleyin ve mevcut değerin kalan dört komşuya eşit mi, yoksa eşit mi, yukarı, aşağı, sola ve sağa eşit olup olmadığına bakın. Ardından yukarıdaki kurala dayanarak mevcut değeri dönüştürün ve değer 0'a eşitse, "" yapın. .

Kod Açıklaması

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";

Burada çevrimiçi deneyin


5
Söylemeliyim ki, CJam kodunu tanımlarken nadiren "çok uzun" duyabiliyorum.
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('')

Firefox / FireBug konsolunda test edin

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'))

Çıktı

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


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


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

4

Python 2: 154 bayt

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

Girdi biçiminde olmalıdır "00001\n00000\n00000\n10000".

Bir dizeyi 2B matrise dönüştürmek Python'da oldukça uzundur. Böylece orijinal dize biçimini korurum. Girdi üzerinde numaralandırıyorum i, indeks, vchar (char) (Sonunda bir golf çözümünde kaydedilen bayt numaralandırmak !!). Her çift (i,v)için doğru çıktı sırasını hesaplarım ve birleştiririm. Doğru çıktı karakterini nasıl seçerim? Eğer v == '\n', çıktı karakter olan \no v == '0', çıkış karakter daha '.'. Aksi takdirde ben 4 komşuları test etmek vvardır, b[i-b.index('\n')-1](yukarıda), b[i-1](sol, b[i+1](sağda) ve b[i+b.index('\n')+1]eğer olurlarsa, () altında <= vkömürleşmesini seçebilir '-'veyav. Burada sayıları değil, karakterleri karşılaştırıyorum, fakat ascii değerleri doğru sırada olduğundan oldukça iyi çalışıyor. Ayrıca hiçbir sorunları, eğerb[i-1]veya b[i+1]eşit '\n', çünkü ord('\n') = 10.

Pyth: 61 58

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

Python betiğinin çevirisi. Oldukça çirkin ;-)

Çevrimiçi deneyin: Pyth Compiler / Executor Python çözümü ile aynı giriş formatı.

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

4

Perl, 77, 75, 72 70

Standart 2d regex eşleştirme hileleri.

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

Örnek:

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

Burada dene


3

Java, 307 , 304 , 303 , 299 298

Bu kesinlikle bazı Java codegolf için "mükemmel" bir meydan okumadır :)

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]));}}}

Girdi (boru '|' yöntemi):

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

Çıktı:

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

1
Boşluğu kaldırırsanız, bu 288 olabilir char[]r=a[0].replace("|", <--here"").toCharArray().
bcsb1001

1
Bunu farketmedim, teşekkürler! Peki bu 298
Rolf ツ

2

APL, 92

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

Örnek:

       ('.-',⎕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-------

Gördüğüm en uzun APL programı. Bunun standart APL olmadığını not etmek isteyebilirsiniz, çünkü dfns.
FUZxxl

2

Yakut 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}

Özel birşey yok; sadece haritayı tekrarlayın ve mevcut değeri dört komşunun değeri ile karşılaştırın.

Testlerle çevrimiçi olarak çalıştırın: http://ideone.com/AQkOSY


1

R, 223

Şu an bulabildiğim en iyisi hakkında. Dize ile başa çıkmak oldukça pahalıdır. İyileştirme için yer olduğunu düşünüyorum, ancak şu anda göremiyorum

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='')

Test sonucu

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

1

J - 69 bayt

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

Örnekler:

   ([: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--.

Not: (0 : 0)Dizeleri belirtmenin standart J yolu. |Sınırlandırılmış dizeleri de kullanabilirsiniz (sonunda |).


1

Excel VBA - 426

VBA'nın herhangi bir kod golf oyununu kazanması nadir bir durum olacaktır, ancak en çok kullandığım şey olduğu için onunla oynamak eğlencelidir. İlk satır, bunu olması gerekenden daha uzun süren bir uç durumdur.

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

Sayı, ilk satır boşluk içermez.

Girdiyi bir sayfaya gönderme ve oradan çalışma düşüncesiyle oynadım, ancak geçirilen dizgiyi karakter karaktere dönüştürmenin kod kaydettiğini düşünüyorum.

Hemen Pencereden Arama:

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

Çıktı (bir Pencerede):

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

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}

İdeone üzerinde deneyebilirsiniz . Biri açıklama ile ilgilenen varsa, bana bildirin.


Sanırım 226 karakterin var, 227 değil.
Cristian Lupascu

@ w0lf haklıysanız, newline Windows'da olduğumdan beri 2'ye kadar sayıldı.
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

fformda bir dize alan 0001\n0000\n0000\n1000ve istenen dizgeyi döndüren bir işlevdir .

g karakter listelerinin listesini alan ve ((sol, yukarı), bu, (sağ, aşağı)) listelerinin bir listesini döndüren bir işlevdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.