title: Minecraft Chest Placement

text:
# Question
Title: Minecraft Chest Placement
The video game Minecraft is all about placing and removing different types of blocks in the 3D integer lattice that makes up the virtual world. Each lattice point can contain exactly one block or be empty (an "air" block officially). In this challenge, we will only be concerned with one horizontal 2D plane of the 3D world, and one type of block: chests.

Chests let players store items. When two chests are orthogonally adjacent in the same horizontal plane, their textures link up and a double chest with twice the capacity forms. Nothing bigger than a double chest can be made; there are no triple chests nor quadruple chests.

A chest block can only be placed in an empty lattice point if its four orthogonally adjacent points are all empty, or if exactly one contains a chest block that is not already part of a double chest. These placement rules ensure that there can never be any ambiguity about which chest blocks link to form double chests.

For example, suppose `.` is empty space and `C` is a chest: (The numbers are also empty space and just for identification purposes.)

```
.......C..
.1.C2.C3..
........5C
.CC4..CC..
..........

```
* A chest can be placed in spot 1 because its 4 neighbors are empty.
* A chest can be placed in spot 2 because the neighboring chest is not (yet) part of a double chest.
* A chest can't be put in spot 3 because there would be ambiguity over how the double chest forms.
* A chest can't be placed in spot 4 because the neighboring chest is already part of a double chest.
* A chest can be placed in spot 5. The diagonally neighboring double chest doesn't affect anything.

Assuming the area beyond the grid is empty, changing every `.` in the grid to a `*` if a chest could be placed there results in this:

```
******.C**
***C**C.**
*..***..*C
.CC.*.CC.*
*..***..**

```

Not all of the `*` spaces can be occupied with chests at the same time of course, but if you only had one chest, it could be placed in any of them.

# Challenge

Write a program or function that takes in a `.` and `C` grid, and changes every `.` to a `*` if a chest could be placed there, printing or returning the resulting grid.

* Input can be from stdin or a file or as a string argument to a function.
* You may assume the input is well formed - i.e. a perfectly rectangular grid of text, at least 1 character wide and tall, only containing `.` and `C` You may optionally assume there is a trailing newline after the last row (and there may be one in the output).
* You may assume the arrangement of chests in the input is consistent with the rules above. There will never be ambiguities about which chests form double chests.
* If desired, you may use any three distinct printable ASCII characters in place of `.`, `C`, and `*`. You may not use something else in place of newlines.
* All the chests are normal chests. Not trapped chests or ender chests.

# Scoring

The submission with the fewest bytes wins.

<sup>*For a Minecraft related challenge that's a bit more challenging, try Nether Portal Detection.*</sup>

# Answer
# CJam, ~~82 76 66 62 58~~ 54 bytes

```
qN/::~4{[8_]f/[9_]f*z{[{1$8-g)+}*]W%}%}*{_8<\2<8?}f%N*

```

Input format expects `0` for air cell and `8` for a chest cell. Output contains `1` for all cells that can be placed with a Chest.

*UPDATE* : ~~Fixed a bug. Increased by 3 bytes :(~~ golfed further :) . 4 bytes saved thanks to @Sp3000

Example input:

```
0000000800
0008008000
0000000008
0880008808
0000000000

```

Output:

```
1111110811
1110018010
1008800108
0880088008
1008800110

```

I think I am done golfing for now...

**Explanation**

```
qN/::~                   "This part converts the input into array of integer array";
qN/                      "Split input on new line";
   ::~                   "Parse each character in each row as integer";

4{[8_]f/[9_]f*z{[{1$8-g)+}*]W%}%}*

4{   ...z{       W%}%}*  "Run the logic 4 times, first, columns in correct order, then,";
                         "columns in reverse order, then for rows";
  [8_]f/[9_]f*           "Convert adjacent chests represented by two 8 into two 9";
                         "This happens for all the rows in the columns iterations and";
                         "for all the columns in the rows iterations";
  {               }%     "For each row/column";
   [{        }*]         "Reduce and wrap it back in the array";
     :I8-                "Store the second number in I, remove 8 from it";
         g               "Do signum. Now we have -1 for < 8 number, 0 for 8 and 1 for > 8";
          )+I            "Increment to get 0, 1 & 2. Add it to first number and put I back";

{_8<\2<8?}f%N*           "This part converts the output from previous iterations";
                         "to 3 character based final output and prints it";
{        }f%             "Map each row using the code block";
 _8<   8?                "If the value is greater than 7, make it 8, else:";
    \2<                  "If the value is greater than 1, make it 0, else 1";
            N*           "Join the arrays using new line";

```

Try it online here
> 11 votes

# Answer
# .NET Regex (Retina), ~~434~~ ~~416~~ 310 + 1 = 311 bytes

After the last challenge I answered in regex (the Nether Portal Challenge linked to in this challenge), I finally set out to write a command-line tool, which acts as an interpreter for .NET-style regular expressions, so I can answer questions with regex without being challenged that they're not a stand-alone language. I've named it Retina.

Now, this challenge doesn't lend itself very well to a regex submission, but I just had to use Retina now. ;) (Plus, Sp3000 challenged me to do so in chat.) So here it is:

**Regex file**

```
m`(?<=(?=.(.)*).*)(?<=((?<=(?<2>C|C(?(1)!)(\n|(?<-1>.))*)?)C(?=(?<2>C|(\n|(?<-1>.))*(?(1)!)C)?)(()(?(6)!)|(?<=^(?(7)!)(?<-7>.)*C).*\n(.)*()(?(8)!)))?){2}_(?=(?<2>((?(10)!)()|(?(11)!)()(.)*\n.*(?=C(?<-12>.)*(?(12)!)$))(?<=(?<2>C|C(?(1)!)(\n|(?<-1>.))*)?)C(?=(?<2>C|(\n|(?<-1>.))*(?(1)!)C)?))?){2}(?<-2>)?(?(2)!)

```

**Replacement file**

```
*

```

The regex file is mostly just the regex, except that ``` lets you put a few options in the file, in this case simply multiline mode. When given two files, Retina automatically assumes replace-all mode. These two files define a program which reads the input from STDIN and prints the result to STDOUT.

You can also test it on RegexHero and RegexStorm. The regex works both with and without trailing newline, and uses `_` in place of `.`. (Apparently, RegexStorm occasionally has problems if there is no trailing newline, but RegexHero seems to handle either case fine.)

There is a horrible amount of duplication in the regex, and I have a couple of ideas for shortening it significantly... I'll give that a try later and then add an explanation. In the meantime, let me know if you can find any inputs which yield a wrong result.
> 8 votes

# Answer
# J, ~~75 73~~ 68 bytes

```
(+.0j1^i.4)(+:@](LF,@:,.~'*.C'{~>.)(2=f)+.[f]*f=.[:+/|.!.0)'C'&=;._2

```

Uses the format in the question, using `.`/`*`/`C` for space/usable space/chest, respectively.

Edit: fixes a small bug (I accidentally used a torus instead of properly treating the surrounding as empty space).

## Explanation

```
## Preparation
              'C'&=;._2  NB. Map ./C to 0/1, turn into matrix
(+.0j1^i.4)              NB. Compute offsets to shift into each direction
                         NB. (i.e. [[_1 0], [1 0], [0 _1], [0 1]] in any order)

## "Part B"
(2=f)+.[f]*f=.[:+/|.!.0  NB. This part computes a matrix that is 1 for cells that
                         NB. cannot contain a chest:
              [:+/|.!.0  NB. Sum of shifts: shift in each of the four cardinal
                         NB. directions (using the array above) and then sum up.
           f=.           NB. Define this function as `f`; we'll use it some more.
         ]*              NB. Multiply by the "is chest" matrix: this isolates
                         NB. double-chests.
       [f                NB. Sum of shifts--1 for double-chest neighbours.
(2=f)                    NB. Isolate cells with two neighbouring chest.
     +.                  NB. Boolean or--either two neighbouring chests or next
                         NB. to a double-chest.

## Wrap up the result
(+:@] (fmt >.) PartB)    NB. Maximum of the array from the above and twice the "is
 +:@]      >.  PartB     NB. chest" matrix--this is 0,1,2 for '*', '.' or chest,
                         NB. respectively.

## Output formatting
LF,@:,.~'*.C'{~          NB. Format output...
        '*.C'{~          NB. Map 0,1,2 to '*.C' by using the value as index
LF   ,.~                 NB. Append line feed at end of each line
  ,@:                    NB. Ravel into one line

```
> 7 votes

# Answer
# C,193

2 unnecesary newlines for clarity. Changes with respect to ungolfed code include: characters as ascii codes instead of character literals; rearrangement of v=0,strlen, and strchr to save characters (strchr is the ugliest, as it means that a calculation that would otherwise be performed once only, is performed 5 times per cell!)

C functions do not accept strings as arguments or return them as values, so the best I can do is the following: `q` is a pointer to the input string. The function modifies the string and when the function returns the output is found in the original string.

```
g(char*q){int v,j,w,l;
int f(p,d){int s=0,i=w=strchr(q,10)-q+1,r;for(;w/i;i-=i-1?w-1:2)r=p+i,r>-1&r<l&&q[r]==67&&++s&&d&&f(r,0);v|=s>d;}
for(j=l=strlen(q);j--;f(j,1),46-q[j]||v||(q[j]=42))v=0;}

```

To summarize the rules:

a blank square (that does not contain C or newline) can be converted if it has max 1 neighbour with a C

...AND that neighbour has no neighbours with a C.

The function g contains a function f that recurses down from depth 1 to depth 0. With only 2 levels of recursion, a simple `f(r,0)` recursive call will do, there is no need for `f(r,d-1)`!

**Ungolfed code in test program**

Input test string is hardcoded. `gets` and `scanf` will not accept an input string with newlines in it; they chop it into pieces at each newline.

```
char n[]=".......C..\n...C..C...\n.........C\n.CC...CC..\n..........";

g(char*q){

  int v,j,w,l;

  int f(p,d){                    //p=cell to be checked,d=recursion depth
    int s=0,i=w,r;               //sum of C's found so far=0, i=width
    for(;w/i;i-=i-1?w-1:2)       //For i in   w,1,-1,-w   = down,right,left,up
      r=p+i,                     //r=cell adjacent to p
      r>-1&r<l&&q[r]=='C'&&++s   //If r not out of bounds and equal to C, increment s...
        &&d&&f(r,0);             //...and if recursion depth not yet at zero, try again one level deeper.
    v|=s>d;                      //If the local s exceeds d, set global v to true to indicate invalid.
  }

  w=strchr(q,10)-q+1;            //width equals index of first newline + 1
  l=strlen(q);                   //length of whole string;
  for(j=l;j--;)                  //for l-1 .. 0
    v=0,                         //clear v
    f(j,1),                      //and scan to see if it should be set
    '.'-q[j]||v||(q[j]='*');     //if the character is a '.' and v is not invalid, change to '*'
}

main(){
  g(n);
  puts(n);
}

```

**Output based on question example**

```
******.C**
***C**C.**
*..***..*C
.CC.*.CC.*
*..***..**

```
> 4 votes

# Answer
# JavaScript (ES6) 124 ~~129~~

Using characters 0 (\*), 6 (C), 7(.)

```
F=s=>[for(c of(d=[o=~s.search('\n'),-o,1,i=-1],s))
   d.map(j=>t-=s[i+j]==6&&~d.some(k=>s[i+j+k]==6),t=i++)|c<7|t>i&&c
].join('')

```

**Ungolfed** and explained

```
F=s=>
{
  o=~s.search('\n') // offset to prev row (~ is shorter than +1 and sign does not matter)
  d=[o,-o,1,-1] // array of offset to 4 neighbors
  i=-1
  result = '' // in golfed code, use array comprehension to build the result into an array, then join it
  for (c of s) // scan each char
  {
    t = i++ // set a starting value in t and increment current position in i
    d.forEach(j => // for each near cell, offset in j
    {
      if (s[i+j]==6) // if cell contains a Chest, must increment t
      {
        // In golfed code "~some(...)" will be -1(false) or -2(true), using decrement instead of increment
        if (d.some(k=>s[i+j+k]==6)) // look for another Cheast in the neighbor's neighbors
        {
          // more than one chest, position invalid
          t += 2
        }
        else
        {
          t += 1
        }
      }
    })
    if (c < 7 // current cell is not blank
        || t > i) // or t incremented more than once, position invalid
    {
       result += c // curent cell value, unchanged
    }
    else
    {
       result += 0 // mark a valid position
    }
  }
  return result
}

```

**Test** In Firefox/FireBug console

```
a='\
7777777677\n\
7776776777\n\
7777777776\n\
7667776677\n\
7777777777\n';

console.log(F(a))

```

*Output*

```
0000007600
0006006700
0770007706
7667076670
0770007700

```
> 1 votes

# Answer
# Perl, 66

The regexp matching chest conflicts ended up on the long side, so no competing with CJam this time.

```
#!perl -p0
/.
/;$"=".{@-}";s%0%s/\G0/2/r!~/2((.$")?2(.$")?|2$"|$"2)2/s*1%eg

```

Uses 0 and 2 for empty and chest spaces on the input, 1 to mark the spots on the output.

Try it here.
> 1 votes

# Answer
# Python 2 - 281 bytes

```
f=lambda x,y:sum(m[y][x-1:x+2])+m[y-1][x]+m[y+1][x]
m=[];o=''
try:
 while 1:m+=[map(int,'0%s0'%raw_input())]
except:a=len(m[0]);l=len(m);m+=[[0]*a]
for y in range(l*2):
 for x in range(1,a-1):
    if y<l:m[y][x]*=f(x,y)
    else:o+=`2if m[y-l][x]else +(f(x,y-l)<5)`
 if y>=l:print o;o=''

```

*(Lines 8 and 9 are intended with a single tab character, which SE converts to 4 spaces. Every line in this program has either 0 or 1 bytes of leading whitespace.)*

Input: `0` for no chest, `2` for chest
Ouput: `0` for no chest, `2` for existing chest, `1` for possible new chest

---

God, this is horrible. I must be seriously out of practice. I threw every trick I know at it and it came out... well, it came out as 281 bytes, losing to every answer except the one in *regex*, haha. I honestly feel like I golfed it kinda well, so I'm guessing that my algorithm was just less than ideal.

**Ungolfed:**

```
def f(x,y):
    """Given x,y coords of the board, return the sum of that point and all
    adjacent points.
    """
    return (sum(board[y][x-1:x+2]) # (x-1,y) + (x,y) + (x+1,y)
            + board[y-1][x]
            + board[y+1][x])
board=[]
output=''
try:
    while True:
        row = '0%s0' % raw_input() # line from stdin with a leading and trailing 0
        board.append(map(int, row)) # convert to list of ints
except:
    pass # exception is thrown when stdin is empty

board_width = len(board[0])
board_height = len(board)

board.append([0]*board_width) # new row of all 0s

for y in xrange(board_height*2):
    # board_height multiplied by 2 so we can use this loop to simulate two
    for x in xrange(1,board_width-1):
        if y < board_height: # "first loop"
            board[y][x] *= f(x,y) # multiply everything on the board by itself + sum
                                  # of neighbours
                                  # empty cells (0) stay 0 no matter what
                                  # lone chests (2 surrounded by 0) become 2*2==4
                                  # double chests (2 touching another 2) are weird:
                                  # - one chest becomes 2*(2+2)==8
                                  # - the other chest becomes 2*(2+8)==20
        else: # "second loop"
            if board[y - board_height][x] != 0:
                output += '2' # anything not equal to 0 is an existing chest
            else:
                valid = f(x, y - board_height) < 5 # if the sum of neighbours > 4, the
                                                   # current cell is either beside a
                                                   # double chest or more than one
                                                   # single chest
                output += '01'[valid]
    if y >= board_height: # only print during the "second loop"
        print output
        output=''

```
> 0 votes

---
Tags: code-golf
---


title: Decode a Heat Map

text:
# Question
Title: Decode a Heat Map
# Heatmaps

Consider a rectangular room, on whose ceiling we have a thermal camera pointing downward. In the room, there are some number of *heat sources* of intensity `1-9`, the background temperature being `0`. The heat dissipates from each source, dropping by one unit per (non-diagonal) step. For example, the `20x10` room

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

```

contains 9 heat sources, and the temperature gradient shown by the thermal camera is

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

```

In graphical form this might look like:

From the gradient, we can infer the positions and intensities of some heat sources, but not all. For example, all `9`s can always be inferred, since they have the maximal temperature, and so can the `8` in this case, since it produces a local maximum in the gradient. The `2` near the right border can also be inferred, even though it is not at a local maximum, since it does not have another `2` as a neighbor. The `5`s, on the other hand, are not inferred, since their heat might as well be produced by the more intense sources near them. The `0`s are known to contain no heat sources, but all the other tiles may *potentially* contain one. Let's denote the uncertain tiles by hyphens `-`, certain heat sources by the corresponding digits, and certain empty space by periods `.`:

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

```

Your task shall be to produce this inferred pattern from the temperature gradient.

# Rules

You are given the input as a string delimited by either newlines or vertical pipes `|`, whichever is more convenient, and the output shall be of the same form. There may be a trailing delimiter in the input and/or output, but no preceding one. The size of the input may vary, but its width and height are always at least `4`. Both functions and full programs are acceptable. The lowest byte count wins, and standard loopholes are forbidden.

# Additional Test Cases

Input:

```
898778765432100
787667654321100
677656543211210
678765432112321
567654321123210

```

which looks like this in graphical form:

Output:

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

```

Input:

```
7898
8787
7676
6565

```

Output:

```
--9-
8---
----
----

```

Input:

```
00001
00000
00000
10000

```

Output:

```
....1
.....
.....
1....

```

# Answer
# CJam, ~~73 69 62~~ 55 bytes

*UPDATE* : New algorithm. Shorter and more scope for improvement

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

```

**How it works**

The logic is similar to the algorithm below, but here I am not checking for all 4 neighbors in a single iteration. Instead, I use a smaller approach to iterate through all rows and columns in both directions. Here are the steps involved:

* Convert each character into sets of 5. The first 4 will be modified to tell if they are bigger than the adjacent cell in the row while iterating. Last one is for comparison purposes.
* Iterate on each row and reduce on each row. While reducing, I have two 5 character string. I know what kind of iteration is \[0 for rows normal, 1 columns reversed, 2 for rows reversed and 3 for columns normal\] I update the ith character in the first 5 character string and make it 0 if it is smaller than the second.
* After all 4 iterations, if all 5 characters are same and non-zero, that is the local maxima. I map through all 5 characters strings and convert them to either single digit, `.` or `-`.

Here is an example run on a small input:

```
7898
8787
7676
6565

```

After first step:

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

```

After second step:

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

```

After last mapping to single character, final output:

```
--9-
8---
----
----

```

**Code Explanation**:

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

```

Try it here

---

**Older approach**

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

```

**How it works**

The logic is simple, iterate through the grid and see if the current value is greater or equal to the remaining four neighbors - up, down, left and right. Then transform the current value based on the above rule and if the value is equal to 0, make it "." .

**Code Explanation**

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

```

Try it online here
> 10 votes

# Answer
# 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('')

```

**Test** In Firefox/FireBug console

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

```

*Output*

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

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

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

```
> 6 votes

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

```

Input has to be of the form `"00001\n00000\n00000\n10000"`.

Converting a string to a 2D-matrix is quite lengthy in Python. So I keep the original string format. I enumerate over the input, `i` is the index, `v` is the char (Finally enumerate saved bytes in a golf solution!!). For each pair `(i,v)` I compute the correct char of output, and join them. How do I choose the correct output char? If `v == '\n'`, the output char is `\n`, it `v == '0'`, than the output char is `'.'`. Otherwise I test the 4 neighbors of `v`, which are `b[i-b.index('\n')-1]` (above), `b[i-1]` (left, `b[i+1]` (right) and `b[i+b.index('\n')+1]` (under), if they are `<= v` and choose the char `'-'` or `v`. Here I'm comparing chars not the numbers, but it works quite fine, because the ascii values are in the correct order. Also there are no problems, if `b[i-1]` or `b[i+1]` equal `'\n'`, because `ord('\n') = 10`.

# Pyth: ~~61~~ 58

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

```

More or less a translation of the Python script. Quite ugly ;-)

Try it online: Pyth Compiler/Executor Same input format as the Python solution.

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

# Answer
# Perl, ~~77, 75, 72~~ 70

Standard 2d regex matching tricks.

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

```

Example:

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

```

Try it here
> 4 votes

# Answer
# Java, ~~307~~, ~~304~~, ~~303~~, ~~299~~ 298

This is for sure a "perfect" challenge for some 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]));}}}

```

**Input (pipe '|' method):**

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

```

**Output:**

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

```
> 3 votes

# Answer
# APL, 92

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

```

Example:

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

```
> 2 votes

# Answer
# 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}

```

Nothing special; just iterate through the map and compare the current value with the value of the four neighbors.

Run it online with tests: http://ideone.com/AQkOSY
> 2 votes

# Answer
## 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}

```

You can try it on ideone. If anyone is interested in an explanation, let me know.
> 1 votes

# Answer
# R, 223

About the best I can come up with at the moment. Dealing with the string is quite expensive. I think there is room for improvement, but can't see it at the moment

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

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

# Answer
## J - 69 bytes

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

```

Examples:

```
   ([: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: the `(0 : 0)` is the standard J way of specifying strings. You might as well use `|` delimited strings (with a trailing `|`).
> 1 votes

# Answer
# Excel VBA - 426

It'll be a rare occasion that VBA wins any code golf games, but as it's what I use the most, it's fun to play around with it. The first line is an edge case that made this longer than it seems it should have to be.

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

```

The count doesn't include initial line whitespace.

I played around with the idea of sending the input to a sheet and working from there, but I think looping the passed string character-by-character saves code.

Call from Immediate Window:

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

```

Output (in a Window):

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

```
> 1 votes

# Answer
# 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` is a funtion that takes a string in the form `0001\n0000\n0000\n1000` and returns the required string.

`g` is a function that takes a list of lists of chars and returns a list of lists of ((left, up), this, (right, down)).
> 1 votes

---
Tags: code-golf, ascii-art
---