Giải mã bản đồ nhiệt


32

Bản đồ nhiệt

Hãy xem xét một căn phòng hình chữ nhật, trên trần nhà chúng ta có một máy ảnh nhiệt hướng xuống dưới. Trong phòng, có một số nguồn nhiệt cường độ 1-9, nhiệt độ nền 0. Nhiệt lượng tỏa ra từ mỗi nguồn, giảm một đơn vị trên mỗi bước (không chéo). Ví dụ, 20x10phòng

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

chứa 9 nguồn nhiệt và độ dốc nhiệt độ được hiển thị bởi camera nhiệt là

34565432100100000000
45676543210000000000
56787654321000000110
45676543210000001221
34565432100000012321
23454321000000123432
12343210000001234543
01232100000012345654
00121000000011234543
00010000000121123432

Ở dạng đồ họa, nó có thể trông như sau:

sơ đồ nhiệt gồm 9 nguồn

Từ độ dốc, chúng ta có thể suy ra vị trí và cường độ của một số nguồn nhiệt, nhưng không phải tất cả. Ví dụ, tất cả các 9s luôn có thể được suy ra, vì chúng có nhiệt độ tối đa, và 8trong trường hợp này cũng vậy, vì nó tạo ra một cực đại cục bộ trong gradient. Đường 2viền gần bên phải cũng có thể được suy ra, mặc dù nó không ở mức tối đa cục bộ, vì nó không có đường viền khác 2như hàng xóm. Mặt 5khác, không được suy ra, vì sức nóng của chúng cũng có thể được tạo ra bởi các nguồn mạnh hơn gần chúng. Các 0s được biết là không chứa nguồn nhiệt, nhưng tất cả các ô khác có thể có khả năng chứa một. Hãy biểu thị các gạch không chắc chắn bằng dấu gạch nối-, các nguồn nhiệt nhất định theo các chữ số tương ứng và không gian trống nhất định theo các khoảng thời gian .:

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

Nhiệm vụ của bạn là tạo ra mẫu suy ra từ gradient nhiệt độ.

Quy tắc

Bạn được cung cấp đầu vào dưới dạng một chuỗi được giới hạn bởi các dòng mới hoặc ống dọc |, tùy theo điều kiện nào thuận tiện hơn và đầu ra phải có cùng dạng. Có thể có một dấu phân cách ở đầu vào và / hoặc đầu ra, nhưng không có dấu phân cách trước. Kích thước của đầu vào có thể khác nhau, nhưng chiều rộng và chiều cao của nó luôn luôn ít nhất 4. Cả hai chức năng và chương trình đầy đủ đều được chấp nhận. Số byte thấp nhất sẽ thắng và các lỗ hổng tiêu chuẩn bị cấm.

Các trường hợp kiểm tra bổ sung

Đầu vào:

898778765432100
787667654321100
677656543211210
678765432112321
567654321123210

trông giống như thế này ở dạng đồ họa:

trường hợp kiểm tra 1

Đầu ra:

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

Đầu vào:

7898
8787
7676
6565

Đầu ra:

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

Đầu vào:

00001
00000
00000
10000

Đầu ra:

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

1
Bạn có phiền nếu tôi thêm 2 đồ họa Heatmap vào câu hỏi của bạn nếu bạn nghĩ rằng chúng thêm giá trị? Họ chỉ là một thử nghiệm 2 phút.
Logic Knight

@CarpetPython Chắc chắn, hãy tiếp tục. Họ trông rất đẹp với tôi. Bạn cũng có thể thêm một "Phép lịch sự của RugPython" để cung cấp cho mình khoản tín dụng. ;)
Zgarb

2
Làm xong. Không yêu cầu tín dụng, nhưng tôi nghĩ sẽ không thô lỗ nếu không hỏi trước khi chỉnh sửa.
Logic Knight

Tại sao không cho phép đầu vào dưới dạng mảng 2 chiều thay vì chuỗi?
frageum

@feersum nói chung phương thức nhập là nhất quán.
Trình tối ưu hóa

Câu trả lời:


10

CJam, 73 69 62 55 byte

CẬP NHẬT : Thuật toán mới. Ngắn hơn và nhiều phạm vi để cải thiện

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

Làm thế nào nó hoạt động

Logic tương tự như thuật toán bên dưới, nhưng ở đây tôi không kiểm tra cả 4 hàng xóm trong một lần lặp. Thay vào đó, tôi sử dụng một cách tiếp cận nhỏ hơn để lặp qua tất cả các hàng và cột theo cả hai hướng. Dưới đây là các bước liên quan:

  • Chuyển đổi mỗi ký tự thành các bộ 5. 4 đầu tiên sẽ được sửa đổi để cho biết nếu chúng lớn hơn ô liền kề trong hàng trong khi lặp. Cuối cùng là cho mục đích so sánh.
  • Lặp lại trên mỗi hàng và giảm trên mỗi hàng. Trong khi giảm, tôi có hai chuỗi 5 ký tự. Tôi biết loại lặp nào là [0 cho các hàng bình thường, 1 cột đảo ngược, 2 cho các hàng đảo ngược và 3 cho các cột bình thường] Tôi cập nhật ký tự thứ i trong chuỗi 5 ký tự đầu tiên và làm cho nó 0 nếu nó nhỏ hơn số thứ hai .
  • Sau tất cả 4 lần lặp, nếu tất cả 5 ký tự giống nhau và khác không, đó là cực đại cục bộ. Tôi ánh xạ qua tất cả các chuỗi 5 ký tự và chuyển đổi chúng thành một chữ số .hoặc -.

Dưới đây là một ví dụ chạy trên một đầu vào nhỏ:

7898
8787
7676
6565

Sau bước đầu tiên:

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

Sau bước thứ hai:

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

Sau khi ánh xạ cuối cùng thành ký tự đơn, đầu ra cuối cùng:

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

Giải thích mã :

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

Hãy thử nó ở đây


Phương pháp cũ hơn

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

Làm thế nào nó hoạt động

Logic rất đơn giản, lặp qua lưới và xem giá trị hiện tại lớn hơn hoặc bằng bốn hàng xóm còn lại - lên, xuống, trái và phải. Sau đó chuyển đổi giá trị hiện tại dựa trên quy tắc trên và nếu giá trị bằng 0, hãy đặt giá trị đó "." .

Giải thích mã

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

Dùng thử trực tuyến tại đây


5
Tôi phải nói rằng, tôi hiếm khi nghe "quá lâu" khi mô tả mã 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('')

Kiểm tra trong bảng điều khiển Firefox / 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'))

Đầu ra

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


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


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

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

Đầu vào phải có dạng "00001\n00000\n00000\n10000".

Chuyển đổi một chuỗi thành ma trận 2D khá dài trong Python. Vì vậy, tôi giữ định dạng chuỗi gốc. Tôi liệt kê đầu vào, ilà chỉ mục, vlà char (Cuối cùng là liệt kê các byte đã lưu trong một giải pháp golf !!). Đối với mỗi cặp, (i,v)tôi tính char chính xác của đầu ra và tham gia chúng. Làm thế nào để tôi chọn char đầu ra chính xác? Nếu v == '\n', char đầu ra là \n, nó v == '0', hơn char đầu ra là '.'. Mặt khác, tôi kiểm tra 4 hàng xóm của v, đó là b[i-b.index('\n')-1](ở trên), b[i-1](trái, b[i+1](phải) và b[i+b.index('\n')+1](dưới), nếu có <= vvà chọn char '-'hoặcv. Ở đây tôi đang so sánh các ký tự không phải là số, nhưng nó hoạt động khá tốt, bởi vì các giá trị ascii theo đúng thứ tự. Ngoài ra không có vấn đề, nếu b[i-1]hoặc b[i+1]bằng '\n', bởi vì ord('\n') = 10.

Số: 61 58

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

Nhiều hơn hoặc ít hơn một bản dịch của kịch bản Python. Khá xấu xí ;-)

Dùng thử trực tuyến: Trình biên dịch / Trình thực thi Pyth Định dạng đầu vào tương tự như giải pháp 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

4

Perl, 77, 75, 72 70

Thủ thuật kết hợp regex 2d tiêu chuẩn.

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

Thí dụ:

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

Hãy thử nó ở đây


3

Java, 307 , 304 , 303 , 299 298

Đây chắc chắn là một thách thức "hoàn hảo" đối với một số 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]));}}}

Đầu vào (phương thức 'ống'):

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

Đầu ra:

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

1
Điều này có thể là 288 nếu bạn loại bỏ không gian trong char[]r=a[0].replace("|", <--here"").toCharArray().
bcsb1001

1
Không phát hiện ra cái đó, cảm ơn! Chà, điều này làm cho 298
Rolf

2

APL, 92

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

Thí dụ:

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

Chương trình APL dài nhất tôi từng thấy. Bạn có thể muốn lưu ý rằng đây không phải là APL tiêu chuẩn vì nó sử dụng 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}

Không có gì đặc biệt; chỉ cần lặp qua bản đồ và so sánh giá trị hiện tại với giá trị của bốn hàng xóm.

Chạy nó trực tuyến với các bài kiểm tra: http://ideone.com/AQkOSY


1

R, 223

Về điều tốt nhất tôi có thể đưa ra vào lúc này. Đối phó với chuỗi khá tốn kém. Tôi nghĩ rằng có chỗ để cải thiện, nhưng không thể nhìn thấy nó vào lúc này

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

Kết quả kiểm tra

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

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

Ví dụ:

   ([: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)là cách J tiêu chuẩn để chỉ định các chuỗi. Bạn cũng có thể sử dụng các |chuỗi phân cách (có dấu |).


1

VBA Excel - 426

Đây sẽ là một dịp hiếm hoi mà VBA thắng bất kỳ trò chơi golf mã nào, nhưng vì đó là thứ tôi sử dụng nhiều nhất, thật vui khi chơi xung quanh nó. Dòng đầu tiên là một trường hợp cạnh làm cho nó dài hơn nó có vẻ phải như vậy.

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

Số lượng không bao gồm khoảng trắng dòng ban đầu.

Tôi đã chơi xung quanh với ý tưởng gửi đầu vào vào một trang tính và làm việc từ đó, nhưng tôi nghĩ rằng việc lặp chuỗi ký tự từng ký tự được truyền sẽ tiết kiệm mã.

Cuộc gọi từ cửa sổ ngay lập tức:

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

Đầu ra (trong một cửa sổ):

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

Bạn có thể thử nó trên ideone . Nếu bất cứ ai quan tâm đến một lời giải thích, cho tôi biết.


Tôi nghĩ rằng bạn có 226 ký tự, không phải 227.
Cristian Lupascu

@ w0lf bạn nói đúng, dòng mới được tính cho 2 kể từ khi tôi vào 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

f là một chức năng có một chuỗi trong mẫu 0001\n0000\n0000\n1000 và trả về chuỗi cần thiết.

g là một hàm lấy danh sách các danh sách ký tự và trả về danh sách các danh sách ((trái, lên), này, (phải, xuống)).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.