2

So,preparing myself for the next ieextreme competition I was going through some past problems.I found one that really troubles me,since I can't figure out what to do.I could probably make it using some bruteforce 300 lines code,but I think that this is not what someone is supposed to do in such competitions,so I need your help!!

Detecting shapes in a bitmap

Problem statement: In image analysis, it is common to analyze a bitmap and observe the shapes present in it. For this problem, design an algorithm to detect shapes in a given bitmap. The shapes present in the map shall be from the set Square, Rectangle, Triangle and Parallelogram.

In the bitmap each pixel is represented as a bit, 1 - representing black and 0 - representing white. Participants are expected to detect the shapes outlined in black. Input The first line will contain the size of the bit map in pixels represented as (Row,Column).

E.g. 6,8 this means a bit map of 6 rows and 8 columns. The next line will contain a series of decimal digits from 0 to 255 separated by spaces. Each digit will represent a collection of 8 binary bits in the bitmap. IE. 55 represents a binary pattern 00110111.

Note: There can be multiple shapes in a bitmap and NO shapes shall intersect. However there can be shapes nested with each other without any intersection.

Output The shapes present in the bitmap in ascending order of their names, separated by a comma and a space. Eg. Rectangle, Square, Triangle

Note: There is NO linefeed or space at the end of the output If any shape repeats, the output should contain as many repetitions as in the bitmap. ie. If there are 2 squares and one triangle, the output shall be Square, Square, Triangle

Example Set 1

Input:

6 8

0 126 66 66 126 0

Output: Rectangle

Example Set 2

Input:

6 16

0 0 120 120 72 144 73 32 123 192 0 0

Output: Parallelogram, Square

I have written this code so that I can visualize the bitmap and have 2 lists(bitmap in rows and cols)...

rows,cols=(int(i) for i in raw_input().split())
nums=[int(n) for n in raw_input().split()]
mr=[]
for i in range(0,len(nums),cols/8):
    row=''
    for j in range(i,i+cols/8):
        b=bin(nums[j])[2:]
        b='0'*(8-len(b))+b
        row+=b
    mr.append(row)
mc=[''.join([mr[i][j] for i in range(rows)]) for j in range(cols)]

Thank you for your time...Please answer if you can in Python,C++ or Ruby,since these are the languages I can understand or even algorithmically...

Controller
  • 489
  • 7
  • 27

1 Answers1

3

My approach would be something like:

  1. Find the first black pixel (either leftmost-topmost, or topmost-leftmost).
  2. Trace the black path right and down (that is, loop until you hit a white pixel).
  3. 3 cases:

    • The paths have same length: square or triangle. Check the pixel right of the bottomleft pixel to decide (black: square, white: triangle).
    • The paths have different length: rectangle or triangle (? or should they always be 45 degrees?). Check the pixel right of the bottomleft pixel to decide (black: rectangle, white: triangle).
    • One of the paths does not exist: triangle or parallelogram. Assuming the path down did exist: check the pixel right of the bottomleft pixel to decide (black: triangle, white: parallelogram).
  4. Remove the shape and repeat.

You examine every pixel only a constant number of times (not quite sure about that constant), so this should run in time linear in the number of pixels.

Vincent van der Weele
  • 12,927
  • 1
  • 33
  • 61
  • Thanks for your reply! Any ideas for parallelograms? – Controller Oct 22 '13 at 10:09
  • @PavlosTriantafyllou Sorry, I totally missed the parallelogram! I added one extra test. – Vincent van der Weele Oct 22 '13 at 10:15
  • I think there is also something else missing(since I've thought about it for a long time)...Say we find the first black pixel and we find that it has a 4 black dots horizontal path and a 4 black dots vertical one...(your step 2) How do we know that the path closes and forms a shape just by checking the next to bottomleft pixel? – Controller Oct 22 '13 at 10:21
  • @PavlosTriantafyllou in the assignment description it says "The shapes present in the map shall be from the set Square, Rectangle, Triangle and Parallelogram." and "NO shapes shall intersect." So you only need to check for one of the simple shapes (there is no "mean" input). I agree, however, that just checking the first pixel is not enough (that only works if the angle is at least 45 degrees), but you only need to check a few to distinguish between a square and a triangle. – Vincent van der Weele Oct 22 '13 at 10:29
  • I don't know if the assignment description is poorly written,but there was indead "mean" input.I mean that not every black pixel is part of a shape...There are random pixels on the bitmap that may or may not form shapes... – Controller Oct 22 '13 at 10:40
  • @PavlosTriantafyllou ok, then of course my approach makes no sense! Still, you could identify the shape that way and then try to trace the whole shape. If that fails, you apparently found some garbage input. – Vincent van der Weele Oct 22 '13 at 10:52
  • ok...thanks again for your time...If you come up with anything else,I would be glad if you shared it with me... :) – Controller Oct 22 '13 at 10:58