13
\$\begingroup\$

Find Santa and his reindeer in a crowded scene.

Input

Input will be on STDIN and will be a variable number of lines of characters of equal, but variable, length. If Santa (represented by the character S) is in the scene, his sack of presents (represented by the character P) will be in one of the positions adjacent to him (horizontally, vertically or diagonally). His reindeer (each represented by the character R) will all be within the 5x5 square surrounding him. If an S appears in the scene that does not have a sack of presents, or is not accompanied by at least 4 reindeer, then it is not Santa.

Output

The scene cleared of all obfuscation (all non-Santa, non-presents, non-reindeer characters replaced with a space), showing Santa, his sack of presents, and his reindeer - all other characters should be replaced with spaces. If Santa and his reindeer are not in the scene, output it unchanged. It is guaranteed that there will only be one solution, so there will never be more than one valid Santa and he will never be carrying more than one sack of presents.

Examples

In these examples I'm just using the * character to make it easy to see the S, P, and R characters, but your program should be able to handle any ascii character from ! to ` (33 to 96). I've left out lower case characters and above to avoid confusion.

Input:

***********
***********
***********
*****R*****
******P****
*****S*****
*****R*****
****R**R***
***********
***********
***********
***********

Output: (ignore dots, they're to force the page to show the blank lines)

.           
.          
.           
     R     
      P    
     S     
     R     
    R  R   
.           
.           
.           
.           

Input: (not enough reindeer)

***********
***********
***********
***********
******P****
*****S*****
*****R*****
****R**R***
***********
***********
***********
***********

Output:

***********
***********
***********
***********
******P****
*****S*****
*****R*****
****R**R***
***********
***********
***********
***********

Input: (no sack of presents)

***********
***********
***********
*****R*****
***********
*****S*****
*****R*****
****R**R***
***********
***********
***********
***********

Output:

***********
***********
***********
*****R*****
***********
*****S*****
*****R*****
****R**R***
***********
***********
***********
***********

Input: (presents not close enough)

***********
***********
***********
*****R*****
***********
*****S*P***
*****R*****
****R**R***
***********
***********
***********
***********

Output:

***********
***********
***********
*****R*****
***********
*****S*P***
*****R*****
****R**R***
***********
***********
***********
***********

Input: (one of the reindeer not within the 5x5 square around Santa)

***********
***********
***********
*****R*****
******P****
*****S*****
*****R*****
****R******
*******R***
***********
***********
***********

Output:

***********
***********
***********
*****R*****
******P****
*****S*****
*****R*****
****R******
*******R***
***********
***********
***********

Test Scripts

As in some of my past questions, I've once again butchered some test scripts originally created by Joey and Ventero to provide some test cases for this question:

Usage: ./test [your program and its arguments]

Plain text version of the tests for reference: Plain text

Rewards

Each entry which I can verify that meets the spec, passes the tests and has obviously had some attempt at golfing will receive an upvote from me (so please provide usage instructions with your answer). The shortest solution by the end of 31/12/2013 will be accepted as the winner.

\$\endgroup\$
  • \$\begingroup\$ I realise this is similar to my previous question Facial recognition, but it's been a couple of years since then. Also, I apologise for skipping the Question Sandbox but with it being christmas related it needed to be posted quickly or it wouldn't be relevant. \$\endgroup\$ – Gareth Dec 21 '13 at 12:01
  • \$\begingroup\$ The first example output does not display properly (appears to be smaller size). \$\endgroup\$ – Dennis Jaheruddin Dec 24 '13 at 13:56
  • \$\begingroup\$ @DennisJaheruddin It looks like the Markdown is removing all the blank lines. I've added dots at the start of those lines to show that they're there. Sorry about the confusion. \$\endgroup\$ – Gareth Dec 24 '13 at 16:38
2
\$\begingroup\$

MATLAB: 110 ,95 characters

f=@(x,y) filter2(ones(x),y);a=M==83;b=M==82;c=M==80;d=f(5,a&f(5,b)>3&f(3,c))&(a|b|c);if ~d,M,else,M(~d)=32,end

Not sure about the way input is supposed to be processed, but the rest is pretty straightforward.

Normally formatted version:

f=@(x,y) filter2(ones(x),y);
a=M==83;
b=M==82;
c=M==80;
d=f(5,a&f(5,b)>3&f(3,c))&(a|b|c);
if ~d
  M
else
  M(~d)=32
end

Example input:

M=['***********'
'***********'
'***********'
'*****R*****'
'******P****'
'*****SQL_2*'
'*****R*****'
'****R**R***'
'***********'
'***********'
'***********'
'***********'];
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hmmm, running the test scripts on this is going to be awkward. A quick look over the code suggests that you're only using the examples given above which use * characters as the crowd to make it easier to see the S, P and R characters - whereas the tests in the test script use all ascii characters from 33 (!) up to (and including) 96 (```). I'll make this clear in the question. I've done a plain text version of the tests you need to pass which I'll also add to the question. \$\endgroup\$ – Gareth Dec 21 '13 at 22:48
  • \$\begingroup\$ @Gareth Updated, seems to pass the tests now. Too bad that santa doesn't wear a Quilt, would have saved me at least 2 characters. \$\endgroup\$ – Dennis Jaheruddin Dec 21 '13 at 23:38
  • \$\begingroup\$ Okay. I don't have Matlab so I'm just downloading Octave (which the internets tell me is the best free way to run Matlab code) and will run through the tests in the morning to check. \$\endgroup\$ – Gareth Dec 21 '13 at 23:52
  • \$\begingroup\$ Okay I've checked this and it does appear to meet the spec. The one place it has an unfair advantage is on the input requirements. I've upvoted, but I won't be able to accept it as winner unless it reads input (from a file since it seems Matlab doesn't read from STDIN). \$\endgroup\$ – Gareth Dec 22 '13 at 14:11
  • \$\begingroup\$ You slipped SQL_2 into the sample input... nice :) \$\endgroup\$ – Timtech Dec 22 '13 at 23:45
1
\$\begingroup\$

Python 2 (353 381)

import re,sys
a=sys.stdin.readlines()
h=len(a)
w=len(a[0])
a=''.join(a)+' '*99
print a
b=[''.join(q) for x in range(0,w) for y in range(0,h) for q in [[a[(y+z)*w+x:(y+z)*w+x+5] for z in range(0,5)]]]
for c in b:
 if c[12]=='S' and 'P' in ''.join([c[1+5*z:4+5*z] for z in range(1,4)]) and c.count('R')>3:
  a=re.sub('[^RPS]','.',c)
  w=h=5
for y in range(0,h):
 print a[y*w:(y+1)*w]

First attempt at writing code as compact as possible. Python is not really the language for that, as indentation and newlines are simply required by design. I mainly choose to use this language, because of the way you can play with lists, and strings as lists. A language with easy matrix manipulation would be ideal for this task, but sadly I don't know any of them.

To test thing, something needs to be assigned to a, e.g.

a=['1**********','*2*********','**3********','***4*******','****5*P****','*****S*****','*****,*****','****R**R***','***********','***********','****R******','**RPSRRR***']

Main interesting thing in this code is probably:

b=[''.join(q) for x in range(0,w) for y in range(0,h) for q in [[a[(y+z)*w+x:(y+z)*w+x+5] for z in range(0,5)]]]

which is a fancy way of writing: "b becomes a list of a representation (string of 25 characters) of every 5x5 square in the original representation".

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ While Matlab may have difficulty reading from STDIN, Python doesn't I'm afraid. Reading the input from STDIN is one of the requirements (to make running the test script possible as much as to stop people from coming up with their own input format). \$\endgroup\$ – Gareth Dec 22 '13 at 11:49
  • \$\begingroup\$ oops, totally missed that. \$\endgroup\$ – Sumurai8 Dec 22 '13 at 11:54
  • \$\begingroup\$ Altered the code, but can't test if it actually works here. It should read it in the same format it used to be in. \$\endgroup\$ – Sumurai8 Dec 22 '13 at 12:04
  • \$\begingroup\$ Okay, I've had a chance to run the tests over this now and there's a couple of issues. 1) In cases where Santa is found, the input is output as is before your solution. 2) Your solution is a different size than the input. I've tried to make the question clearer on this point - all non-(santa, presents, reindeer) characters should be replaced with spaces. It was like this in the first example, but it was not stated explicitly in the question. 3) When Santa is not found the output has double line-spacing. \$\endgroup\$ – Gareth Dec 22 '13 at 13:27
0
\$\begingroup\$

There should be only one Santa in file (if more than 2 "S", I need update the code).

Using awk

cat santa.awk

BEGIN{FS=""}
{ for (i=1;i<=NF;i++)
         { a[NR FS i]=$i
           if ($i=="S") {l=NR;c=i}
         }
     }
END{ if (l=="") {print "No Santa";exit}
     for (i=l-1;i<=l+1;i++)
        for (j=c-1;j<=c+1;j++)
          if (a[i FS j]=="P") p++
     if (p<1) {print "Santa has no presents";exit}
     for (i=l-2;i<=l+2;i++)
        for (j=c-2;j<=c+2;j++)
          if (a[i FS j]=="R") r++
     if (r<4) {print "Santa has no enough reindeers";exit}
     else {  print "found Santa "
             for (i=1;i<=NR;i++)
               { for (j=1;j<=NF;j++)
                   if (a[i FS j]~/[R|S|P]/) {printf a[i FS j]} else {printf " "}
                 printf RS
                }
           }
    }

Run awk command as below

awk -f santa.awk file

Result

found Santa



     R
    R R
    PS
    RR
    R  R
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Apologies for not reviewing this sooner (I'm on holiday and don't have easy access to wifi). Unfortunately, 2 S are allowed as long as only one is a 'valid' Santa. The tests (provided in the question) have a couple of cases that would fail for this reason. \$\endgroup\$ – Gareth Dec 30 '13 at 2:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.