rippling | technical phone screen
Anonymous User
5146

/*
Problem
We want to build a very basic app that let artists draw shapes on a blank canvas.
Think of this app like the most rudimentary version of Microsoft Paint or Adobe Photoshop.
We want this app to eventually support the following operations:

add shapes to the canvas

move shapes around the canvas.

Part 1
create a MxN blank canvas

display the canvas to the user

Example:
A canvas of 10x25 would look like this. String “0” means a white space.

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Part 2
draw a rectangle of size LxW and place it at some coordinate (i, j)

supports multiple shapes where the shapes can be overlapping. If they are overlapping, then the last shape that was drawn gets displayed

Example:

Drawing the shapes ‘a', ‘b’ and 'c’ where

'a' is 4x6 at (0,0)

'b' is 6x4 at (4,21)

'c' is 5x5 at (2,5)

Notice ‘c' is overlapping with ‘a’ and since ‘c’ was added last, we show ‘c’ on top of 'a’

a a a a a a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a c c c c c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a c c c c c 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 c c c c c 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 c c c c c 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 c c c c c 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b b b b

Part 3
Move the shape to any new location within the canvas.

Example:
Moving the shape ‘c' to (2, 7). Notice how 'a’ is being displayed to the user.

a a a a a a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a a 0 c c c c c 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a a 0 c c c c c 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 c c c c c 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 c c c c c 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 c c c c c 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b b b b
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b b b b

[ . ]
[ a a a a ]
[ a b a a ]
[ a ]
[ . b . ]
[ b ]
[ c ]

move c out of canvas
[ b ]

move b out of canvas
[ a ]

*/

class Canvas(val r: Int, val c: Int) {
  val g = MutableList(r) { MutableList(c) {'.'} }
  val overwritteng = MutableList(r) { MutableList(c) {'.'} }
  
  fun display() {
    var i = 0
    var j = 0
    println()
    for( i in g.indices ) {
      for( j in g[i].indices ) {
        print( "${g[i][j]} ")
      }
      println()
    }
  }
  
  fun draw( shape: Char, from: Pair<Int,Int>, size: Pair<Int,Int>) { // size.first -> L, size.second -> W
    if( from.first < 0 || from.second < 0 || size.first < 0 || size.second < 0 )
      return
      
    var ri = from.first
    var ci = from.second
    
    var rs = -1
    while( ++rs < size.first ) {
      var cs = -1
      while( ++cs < size.second ) {
        if( ri+rs >= g.size || ci+cs >= g[ri+rs].size)
          continue
        
        if( g[ri+rs][ci+cs] != '.' ) {
          overwritteng[ri+rs][ci+cs] = g[ri+rs][ci+cs]
        }
        
        g[ri+rs][ci+cs] = shape
      }
    }
    return
  }
  
  fun move( from: Pair<Int,Int>, to: Pair<Int,Int> ) {
    if( from.first < 0 || from.second < 0 || to.first < 0 || to.second < 0 )
      return
      
    val moveshape = g[from.first][from.second]
    
    var bound = -1
    var ri = from.first
    while( ri < g.lastIndex && g[++ri][from.second] != moveshape );
    
    val width = ri-from.first
    var ci = from.second
    while( ci < g[from.first].lastIndex && g[from.first][++ci] != moveshape );
    
    val len = ci-from.second
    
    // move lenxwidth shape to to
    
    ri = from.first+len
    
    while( --ri >= from.first ) {
      ci = from.second+width
    
      while( --ci >= from.second ) {
        val tox = to.first+ri-from.first
        val toy = to.second+ci-from.second
        if( tox >= g.size || toy >= g[0].size )
          continue
        
        // todo: handle overlap
        g[tox][toy] = moveshape
        if( overwritteng[ri][ci] != '.' ) {
          g[ri][ci] = overwritteng[ri][ci]
          overwritteng[ri][ci] = '.'
        }
      }
    }
    
    return
  }
}

fun main(vararg args: String) {
  val c = Canvas( 10, 25 )

  c.draw( 'a', Pair(0,0), Pair(4,6))
  c.draw( 'b', Pair(4,21), Pair(6,4))
  c.draw( 'c', Pair(2,5), Pair(5,5))
  
  c.display()
  c.move( Pair(2,5), Pair(2,7))
  c.display()
	println("Hello")
}



// Your last C/C++ code is saved below:
// #include <iostream>
// using namespace std;

// int main() {
// 	cout<<"Hello";
// 	return 0;
// }
Comments (12)