히트 맵 디코딩


32

히트 맵

천장에 열 카메라가 아래쪽을 향한 직사각형 방을 생각해보십시오. 방에, 몇개있다 열원 강도 1-9백그라운드 온도 존재 0. 열은 각 소스에서 발산되어 (대각선이 아닌) 단계마다 1 단위 씩 떨어집니다. 예를 들어, 20x10

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

9 개의 열원을 포함하고 열상 카메라가 보여주는 온도 구배는

34565432100100000000
45676543210000000000
56787654321000000110
45676543210000001221
34565432100000012321
23454321000000123432
12343210000001234543
01232100000012345654
00121000000011234543
00010000000121123432

그래픽 형식으로 다음과 같이 보일 수 있습니다.

9 가지 소스의 히트 맵

그래디언트에서 일부 열원의 위치와 강도를 유추 할 수 있지만 전부는 아닙니다. 예를 들어, 모든 9온도는 최대 온도를 갖기 때문에 항상 추론 될 수 있으며 8,이 경우 기울기에서 로컬 최대 값을 생성하기 때문에이 경우도 마찬가지입니다. 2근처의 오른쪽 테두리는 그것이 다른이 없기 때문에, 현지 최대 아니더라도, 추론 될 수있는 2이웃으로. 반면에 5s는 열이 주변의 더 강렬한 근원에 의해 생성 될 수 있기 때문에 추론되지 않습니다. 0들에는 열원을 포함하지 않는 것으로 알려져 있습니다 만, 다른 모든 타일이 수 잠재적으로 하나를 포함한다. 불확실한 타일을 하이픈으로 표시합시다-, 특정 열원은 해당 숫자로 표시되고 특정 빈 공간은 마침표로 표시됩니다 ..

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

당신의 임무는 온도 구배로부터이 추론 된 패턴을 생성하는 것입니다.

규칙

줄 바꿈이나 세로 파이프로 구분 된 문자열을 입력 할 수 있으며 |, 둘 중 더 편리한 방법이 있으며 출력 형식은 동일해야합니다. 입력 및 / 또는 출력에 후행 구분 기호가있을 수 있지만 선행 구분 기호는 없습니다. 입력의 크기는 다를 수 있지만 너비와 높이는 항상 최소한 4입니다. 기능과 전체 프로그램이 모두 허용됩니다. 가장 낮은 바이트 수가 이기고 표준 허점은 금지됩니다.

추가 테스트 사례

입력:

898778765432100
787667654321100
677656543211210
678765432112321
567654321123210

그래픽 형식으로 다음과 같습니다.

테스트 사례 1

산출:

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

입력:

7898
8787
7676
6565

산출:

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

입력:

00001
00000
00000
10000

산출:

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

1
가치가 있다고 생각되면 질문에 2 개의 히트 맵 그래픽을 추가해도 될까요? 그들은 단지 2 분의 실험이다.
Logic Knight

@CarpetPython 물론입니다. 그들은 나에게 아주 좋아 보인다. "CarpetPython 제공"을 추가하여 크레딧을 제공 할 수도 있습니다. ;)
Zgarb 2019

2
끝난. 크레딧은 필요하지 않지만 편집하기 전에 묻지 않는 것이 무례하다고 생각했습니다.
논리 기사

입력을 문자열 대신 2 차원 배열로 허용하지 않는 이유는 무엇입니까?
feersum

@feersum은 일반적으로 입력 방법이 일치합니다.
Optimizer

답변:


10

CJam, 73 69 62 55 바이트

업데이트 : 새로운 알고리즘. 개선을위한 더 짧고 더 넓은 범위

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

작동 원리

논리는 아래 알고리즘과 유사하지만 여기서는 단일 반복에서 4 개의 이웃을 모두 확인하지는 않습니다. 대신, 작은 행의 접근 방식을 사용하여 모든 행과 열을 양방향으로 반복합니다. 관련된 단계는 다음과 같습니다.

  • 각 문자를 5의 세트로 변환하십시오. 첫 번째 4는 반복되는 동안 행의 인접한 셀보다 큰지 알 수 있도록 수정됩니다. 마지막은 비교 목적입니다.
  • 각 행을 반복하고 각 행을 줄입니다. 줄이면서 두 개의 5 문자열이 있습니다. [반복 행의 경우 0, 반전 된 행의 경우 2, 반전 된 행의 경우 2 및 반전 된 행의 경우]이 어떤 반복인지 알고 있습니다 . 첫 번째 5 개의 문자열에서 i 번째 문자를 업데이트 하고 두 번째보다 작 으면 0으로 만듭니다. .
  • 4 개의 모든 반복 후에 5 개의 문자가 모두 같고 0이 아닌 경우 이는 로컬 최대 값입니다. 5 개의 문자열을 모두 매핑하여 한 자리 .또는 로 변환합니다 -.

다음은 작은 입력에서 실행되는 예입니다.

7898
8787
7676
6565

첫 단계 후 :

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

두 번째 단계 후 :

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

단일 문자에 마지막으로 매핑 한 후 최종 출력 :

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

코드 설명 :

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

여기 사용해보십시오


이전 접근법

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

작동 원리

논리는 간단하고 그리드를 반복하며 현재 값이 나머지 네 이웃 (위, 아래, 왼쪽 및 오른쪽)보다 크거나 같은지 확인합니다. 그런 다음 위의 규칙에 따라 현재 값을 변환하고 값이 0이면 "."로 만듭니다. .

코드 설명

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

여기에서 온라인으로 사용해보십시오


5
CJam 코드를 설명 할 때 "너무 길다"는 말은 거의 없다.
Alex A.

6

자바 스크립트 (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 콘솔에서 테스트

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

산출

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


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


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

4

파이썬 2 : 154 바이트

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

입력은 형식이어야합니다 "00001\n00000\n00000\n10000".

파이썬에서 문자열을 2D 행렬로 변환하는 것은 상당히 길다. 그래서 원래 문자열 형식을 유지합니다. 입력을 열거하고, i색인 v이며, 문자입니다 (마지막으로 저장된 바이트를 골프 솔루션에 열거합니다 !!). 각 쌍에 (i,v)대해 올바른 출력 문자를 계산하고 결합합니다. 올바른 출력 문자를 어떻게 선택합니까? 만약 v == '\n', 출력 문자는 \n그것이 v == '0'출력 문자가보다 '.'. 그렇지 않으면 나는의 4 개 이웃 테스트 v하고, b[i-b.index('\n')-1](이상), b[i-1](왼쪽 b[i+1](오른쪽)과 b[i+b.index('\n')+1]그들이 경우, () 아래를 <= v하고 문자를 선택 '-'하거나v. 여기서는 숫자가 아닌 문자를 비교하고 있지만 ASCII 값이 올바른 순서이므로 제대로 작동합니다. 또한 거기에 아무런 문제가 없으며, 경우 b[i-1]또는 b[i+1]동일 '\n'때문에 ord('\n') = 10.

피스 : 61 58

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

파이썬 스크립트의 번역. 아주 못생긴 ;-)

온라인 사용해보십시오 : Pyth Compiler / Executor 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

펄, 77, 75, 72 70

표준 2D 정규식 일치 트릭.

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

예:

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

여기 사용해보십시오


3

자바, 307 , 304 , 303 , 299 298

이것은 일부 Java codegolf에 대한 "완벽한"도전입니다. :)

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

입력 (파이프 '|'방법) :

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

산출:

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

1
에서 공백을 제거하면 288이 될 수 있습니다 char[]r=a[0].replace("|", <--here"").toCharArray().
bcsb1001 2019

1
고마워요! 이건 298
Rolf ツ

2

APL, 92

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

예:

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

내가 본 것 중 가장 긴 APL 프로그램. 이것은 dfn을 사용하므로 표준 APL이 아니라는 점에 유의하십시오.
FUZxxl

2

루비 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}

특별한 것은 없습니다. 지도를 반복하고 현재 값을 네 이웃 값과 비교하십시오.

테스트를 통해 온라인으로 실행하십시오 : http://ideone.com/AQkOSY


1

제 223 화

내가 지금 할 수있는 최선에 대해. 끈을 다루는 것은 꽤 비쌉니다. 개선의 여지가 있다고 생각하지만 지금은 볼 수 없습니다

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

시험 결과

> 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 바이트

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

예 :

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

추신 :는 (0 : 0)문자열을 지정하는 표준 J 방법입니다. |구분 문자열 (후행 |)을 사용할 수도 있습니다 .


1

엑셀 VBA-426

VBA가 모든 코드 골프 게임에서이기는 경우는 드물지만 가장 많이 사용하는 게임이므로 재미있게 놀 수 있습니다. 첫 번째 줄은 필요한 것보다 길게 만든 가장자리 케이스입니다.

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

카운트에는 초기 줄 공백이 포함되지 않습니다.

입력을 시트로 보내고 거기에서 작업한다는 아이디어로 놀았 지 만 전달 된 문자열을 문자별로 반복하면 코드가 저장된다고 생각합니다.

즉시 창에서 전화 :

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

출력 (창에서) :

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

1

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

ideone에서 시도해 볼 수 있습니다 . 설명에 관심이있는 사람이 있으면 알려주십시오.


난 당신이 226 개 문자가 아닌 227 생각
크리스티안 루파 스쿠

@ w0lf 맞습니다 .Windows를 시작한 이후 줄 바꿈이 2로 계산되었습니다.
hmatt1

1

하스켈-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형식의 문자열을 가져와 0001\n0000\n0000\n1000필요한 문자열을 반환 하는 함수입니다 .

g 문자 목록의 목록을 가져 와서 ((왼쪽, 위), this, (오른쪽, 아래)) 목록 목록을 반환하는 함수입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.