## Tuesday, January 31, 2017

### 1. Gemini Monster.

Game Designer: Hi dev, you still remember those normal monster?

Dev: yeah, sure

Game Designer: I'd like to add a few of them.

Dev: Ok, doesn't need lot of code.

Game Designer: Here's the tweak.. It is first treated as normal summon, and then when it is on the field you can normal summon it again to make it an effect monster. Off course, when it dies, it's a normal monster again.

Dev: Wat...

Conclusion: Yeah, let's make an effect monster with an effect that treated as normal monster and can be summoned twice.

### 2. XYZ Summon

Game Designer: We need new summon mechanic

Dev: OK.

Game Designer: let's call it XYZ summon so the XYZ monster, should first be in the extra deck.

Dev: Ok.

Game Designer: well, you can summon it similar to synchro and fusion, except when it is summoned, you put the materials below it.

Dev: That's a pain.

Game Designer: Oh and monster that become material doesn't treated as leaving the field by the way, just call it they are in limbo space.

Dev: ...

Game Designer: And when the material is sent to graveyard, they are not considered to be sent from field as well.

Dev: ...

### 3. Pendulum Summon.

Game Designer: Let's make a monster that could be treated as spell card as well!

Dev: Watever.

## Monday, January 9, 2017

### Facebook Hacker Cup Qualification Round - 2017

This is probably the first time I've ever solved all problems in Programming Competition. So, as to commemorate the event, I'm writing my solution about the problems.

Problem 1:
you can view it here.
question: given N percentage of a circle with radius 50 and center at (50, 50), determine whether point at (X, Y) is within that circle or not.

This problem is quite obvious, in this problem we just need to figure out the degree and distance of (X, Y) from (50, 50).
The distance can be measured using basic trigonometry
r = sqrt(dx^2 + dy^2)
The degree can be measured with
arccos(dx / r)
Though we'll need a little tweak based on which quarter it's placed on.

tag: Mathematic, Trigonometry, Implementation

Problem 2:
can be viewed here.
problem is too long to be explained, checkout that link.

This is a problem where, if you feel confused, just try to implement it.
The solution here is just to order the items in the descending order (or ascending if you're using stack).
1. Pick the most heavy item (last in the ascending ordered stack), we will call it X
2. Based on that item, also pick n - 1 item starting from the lightest where n = Math.ceil(50 / B)
3. keep doing it, until all (X * n) < 50.

for example if our items:
[50, 30, 30, 10, 6, 5, 4, 3, 2, 1, 1, 1]
our pick will be:

• 50
• 30 and 1
• 30 and 1
• 10 and 1, 2, 3, 4
• 5 and 6 is left, we can ignore them and just assume that he has delivered it in the previous delivery.

tag: Greedy

Problem 3:
details can be viewed here
tl;dr: given N dice with M side, figure out the probability that the sums of all dice is greater than X.

Ok, this one, is harder (Actually, I literally figured out the answer right after I wake up the next day lol).

### The thought process:

Ok, I start with: ... I know this is probably binomial distribution, normal distribution, pascal triangle or something... but I couldn't figure out how I can use it to solve this problem?

 Pascal Triangle for 2 sided coin.
After a few times of thinking..., well doesn't hurt to get some insight, let's write some simulation... probably something like this?

 Random Dice Generator.
For non-rubyist, that code basically create 100.000 simulation throwing <dice>-sided dice <n>-times. and get the sum of those dices.
 Value distribution for throwing 3-sided-dice two times.
Ok, that looks exactly like 1, 2, 3, 2, 1
 Value distribution for throwing 3-sided-dice three times.
Now this one is harder, it looks like 1, 3, 6, 7, 6, 3, 1, but I'm not really sure.

What if instead of throwing random simulation, we look exactly at the actual possible values?
 Simulation2
Calculating the frequency of each value from that code get us exactly: [1,2,3,2,1].
Neat, the first one is correct, what about the 2nd one?

Let's just change our function a bit.
 Fuck reusability, reliability, readability, and speed lol.
Calculating the frequency of each values gave us: [1, 3, 6, 7, 6, 3, 1].
Whoa, neat!

Now how can we generalize these values? By creating the Generalized Pascal Triangle
I don't really know how I get it, this is the point where it just struck your head or something.

 Pascal Triangle for 4-sided-dice

 Pascal Triangle for 6-sided-dice

How do we generate these triangles?
For 2 sided coin, everyone probably knows that:
pt2[x] = pt2.parent[x - 1] + pt2.parent[x]

or, if you're more mathematic wired, we can represent it like this as well:
pt2[x] = pt2[x - 1, y - 1] + pt2[x, y - 1]
So, how about 4 sided dice?
It's not much different.
pt4[x] = pt4[x - 3, y -1] + pt4[x - 2,  y - 1] + pt4[x - 1, y - 1] + pt4[x, y - 1]
Notice the formula?
yeah, it is:
ptN[x] = sum(ptN[x - N + i, y] for i in xrange(1, N - 1))
legends: ptN[x, y] = Pascal Triangle for N sided-dice at (x, y)
can we optimize this calculation? yeah, we can, but it's not necessary, (be warned, I don't actually implemented this, so I can't guarantee the formula, it might have an off-by-one-error)
ptAN[x, y] = ptAN[x - N + i, y] + ptN[x, y]
legends: ptAN[x, y] = Pascal Triangle Accumulative Value.
it's probably also more useful to store its accumulative value instead of its actual value, so my array would look like this:
 Pascal Triangle (Accumulative) for 4 sided dice.
This way, if I were to figure out the probability of X >= X' when you throw 4 sided dice with value (0, 1, 2, 3) 2 times.
I just need to calculate:
P(X >= X') = ptA4[X', 2] / ptA4[0, 2]
Notice that I said the value of our dice is (0, 1, 2, 3) while the value of dice in the problem is (1, 2, 3, 4), so we should also tweak our implementation a little. The good part is it is trivial, but the bad part  it's also where the bugs may arise from.

As for closing remarks:
I personally consider these problems a good one actually, or not, it's just that I like these kind of question because it fit my strong point.

Finally, have this gem from 2011.

## Monday, January 2, 2017

### Ruby, Metaprogramming, and LinearEquation Solver

Metaprogramming
Metaprogramming is a programming technique in which computer programs have the ability to treat programs as their data. It means that a program could be designed to read, generate, analyse or transform other programs, and even modify itself while running. ~ Wikipedia.
In Ruby, there's an enormous amount of function, that would help you writing a program, that could dynamically modify itself.

Most common example is:
• define_method(methodname, &block)

define_method is a method that take two argument, a symbol or string as the methodname, and the block process of what it should do.

for example, if I have a class, that refer to a user table in mysql with field name, email, and password, i can define 3 new method dynamically, namely find_by_name, find_by_email, and find_by_password with the following code: (not accurate, but you get the point)

• method_missing?(methodname)

method missing is a method that just accept a string or symbol argument, this is a method that allows you to handle any arbitrary method when it is called.
Suppose your User have a field name, email, and password, and then there's user info where we put his address, facebook_id, phone_number, and so on. Now you might want to write your program so that a User object may receive any method in UserInfo, well, it'll probably be written like:

Alright, so we've seen how we can write a program that could modify itself mid-runtime, or defining what is not defined. Since we've seen how we write a program that "write" itself, it's also possible for our program to read its own source-code.

### Meet the "source-code".

In the next example, We'll look how we implement a linear-equation solver using metaprogramming, (not really useful since then, our equation is hardcoded, but why not?).

Look at the following example of how we define our equation:

Guess what, there's no variable x, y, or z in program, we also didn't create new behavior for Fixnum instance by defining .x, .y, or .z method, and of course we doesn't use method_missing? as well.
Would it then throw error? well, no, not until it's evaluated.

If the codes will be an error when it's evaluated, then just don't evaluate it ~ Ramadoka:2017

Which is exactly what I'll do.

Let's take a look at what it does

what magic did we found there?

you might guessed it correctly, it's the @eq.source

that magic, allows us to read the source-code of our function, and since ruby is dynamic-typed interpreted language, it doesn't know whether an object would respond to a method or not, until it is evaluated, so yeah, there won't be a compile time error, as long as our-code passed the lexical analysis.

Now, that we have done it, we basically just said:

"ruby, kindly, don't parse my code, let me handle that part myself."

Which is pretty meta for my taste...

That marks the end of our topic about metaprogramming, but if you're curious about how the code of LinearEquation works, please feel free to continue along.

### Linear Equation Solver

The first step is defining the requirement (can be adjusted later), how do we want to say 3x + 2y + z = 10
since apparently 3x + 2y + z = 10 doesn't pass the lexical analysis (or in other words, ruby know it's not a valid program even without running it).

In this example I'm defining my requirement would be:
3.x => 3x
- x => - x
+ 2 = 10 => not valid (too lazy to reduce to minimum state)
+ z = 10 => + z = 10
+ -x => apparently work as intended
- -x => not working correctly.

If the code doesn't match the requirement, you can either
a) change the code so it meet the requirement
b) change the requirement so it match the code

So Yeah, since this is just a proof of concept, I'm picking the 2nd option.

How do we handle the parsing?

Regex, Regex is always the answer, as anonymous programmer said:

A programmer has a problem, and then he said, I know, I'll use regex.
Now he has 2 problem.

Ok, as you've seen regex is not the silver bullet to handle parsing, we probably need a full-blown parser, but implementing a parser might take 10x time longer than it is, so let's live with the bug now.

as buggy as it is, this regex handles the filtering of a parameter for our basic necessity:
/[+-]* *(?:\d+\.){0,1}[a-zA-Z]+/
by using string.scan using this regex, a 3.x + y + 2.z
will become ["3.x", "+ y", "+2.z"]

and then, there's two other regex to parse our parameters, it can be either:
/(?<multiplier>\d+)\.(?<name>\w+)/

or, it can also be:
/(?<multiplier>)(?<name>[a-z]+)/)
if it doesn't have multiplier (e.g: y)

once we have parsed 3.x - 2.y + z = 10 into
[3x, -2y, 1z] and [10]

We will use Matrix Multiplication to solve the equation:

as it turns out, our equation can be rewritten as Matrix Multiplication as:

Aaaand, that's it, I'm out of material. Thanks for reading this scientific nonsense.

For the full version of the LinearEquation Implementation you can see it here.

Does this post lacking madokaism?, No Longer!

## Sunday, October 12, 2014

### Introduction to Functional Programming

• Eh, wao I could write a function nested inside another function.
• Oh, look, I could pass a function as an argument to another function.
• Oh, wao, look at this, my function returned another function, keeewl.
• What, what is this lambda? awesome, with this I could one-lineize most of my code.
• Closure ?, eh, ao, I can use this to create a function that "magically" return a different value each time it's called?
• ParallelMap!!, a powerful function that eats away my CPU resource to boost computation time!
Damn, I'm such a functional-programmer by abusing all these cool stuff. Screw "def", eat this lambda, and while I'm on it, let's add more magic called "map" and "reduce" to the code to confuse anyone who cared enough to read it.

Well, that little sinful flashback is probably what I have in mind during my Recognition System project, and my definition of Functional Programming.

But, it all changed upon following this course in the coursera. And here, on this post, I'll write an introduction to functional programming.

Q:
So, what is this functional programming?

A:
Apparently, It's not about how you write code, or how you pass a function, or how you write a function that return another function.
It's a paradigm, about how to think of a solution to a problem.

This straight-forward definition of wikipedia, might give you an insight. (though for me it doesn't, until I actually do an exercise myself)
functional programming is a programming paradigm, a style of building the structure and elements of computer programs, that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.

http://en.wikipedia.org/wiki/Functional_programming
If you still doesn't get the gist of it, don't worry, I don't get it either just by reading it the first time.

But now, let's consider the following fibonnaci bottom-up solution, with imperative style written in python.

1. def fib(n):
2.         a = 0
3.         b = 1
4.         for i in xrange(0, n):
5.                 c = a + b
6.                 a = b
7.                 b = c
8.         return a

Now, if we translate that code, into a more human friendly instruction:
• To get the n-th fibonnaci
• first, prepare two container let's call it a and b, and fill it with 0 and 1 respectively.
• repeat the following process up to n-time
• prepare another container called c, and fill it with the sum of a and b
• store the value of b to a
• store the value of c to b
• at the end of the process, the answer is the value stored at container a
That's it, in imperative programming, we literally think a solution to a problem as an instruction to the computer, about how to store a value to a memory, what to be stored, when to be changed, how long an instruction should be repeated, when should it be terminated, and so on.

With that being said, consider the following code, written in scala doing the exact similar thing, except that it's written in recursive.
1. def fib(n: Int): Int
2.         @tailrec
3.         def fibloop(counter: Int, ans1: Int, ans2: Int): Int
4.                 if(counter == 0) ans2
5.                 else fibloop(counter - 1, target, ans1 + ans2, ans1)
6.         fibloop(n, 10)

Now, if we translate it, into something more human friendly instruction, it becomes:

• The n-th fibonacci is:
• The result of fibloop(n, 1, 0)
• But, what is fibloop?
• fibloop is a function that take 3 parameter counter, ans1, and ans2
• it'll return ans2  if counter = 0
• or otherwise, it return the result of fibloop(counter - 1, ans1 + ans2, ans1)
That's it.
In functional programming, we don't write a program that mutate a variable, an instruction that repeated several times, a condition to break out of the loop, or anything along that line, but we write a mathematical expression to a solution of a problem.

You might think, that merely converting an iterative solution, to a recursive one isn't really that much different, and if anything, it might be even worse on performance. However, there's a huge paradigm different between the two.

In the recursive version, A solution to a problem, isn't represented by what instruction should be done, and how many-time it should be repeated.

It's represented, as a simple expression that, once evaluated, answer the given question.

Additionally, the cerebration of recursive, is that:

Instead of going straight ahead solving a difficult problem, we're loooking for a solution of similar problem, but this problem in one-step-easier than that.
Can you solve it now? No? then, consider another problem that's one-step-easier, and so on, until you can solve it :)

To summarize, unlike the imperative-programming, in functional-programming, we didn't write a solution as a computer instruction, but we write it as a mathematical expression. Which means:
• There's no variable assignment.
There's no mutable variable.
There's no law-breaking mathematical expression like x = x + 1.
#But there's a substitution to simplify a long expression like a = e ^ (b + c * d ).
#A
n immutable variable isn't a constant, mind you, it's a variable that doesn't change on the scope it's defined.
• There's no loop, break, assignment,  and other computational-instructions,
• A function, could very well become a parameter, or even return value.
#Remember Integral? yeah that's one example about a function taking an argument of a function, and returned another function).
Okay, that's about everything I want to write in this article, sorry that, there's no higher-order-function, closure, and other functional concept, because what I'm trying to write here is the paradigm itself, instead of the "how-to-code"-tutorial.

Notice the lack of Madoka in this post? Here have this gem.
p.s: yes, this is also another preaching to madokaism.

## Friday, December 21, 2012

### The real reason the world doesn't end in 21-12

What the title said.

## Saturday, December 8, 2012

l7lql          l7lll
77Qlql        l7l Ql
Q7l  lqV      V7l   l
VlQ                         UVVqqqqqqqV QVVVppVVV          V7l   lqQ     77    lV
77mQ                    Vq.........................qqV     l7Q    ml    V7V    ll
Q7lQlV               Vq.................................qV  q7Q    Rql   lq     Vq
Q7Q  lR           Vq.......................................l7q      VqV  ml      mR
V7Q   mQ        V..........................................77qV      lqVQqV      ll
VllQ         l7V   QqQ     p............................................77q..p     VqllQ      Vl
77lqlQ       l7l    Vl   q..............................................77q....V    Qlll Vl  VlV
73VlqqllQQ   V7l     qqq................................................777.....q   V7..q..q7...V
72  Qlmqmq..7777qqq.....................................................777.......Vq.....q..7....V
7l    Qlmll7............q...............................................qq[...............7.7[....V
7l      Vmllllq.......qq................................................ll.......7........q..q.....
7l       QlmlVVlllllllq................................................7ll.................7.7......
7l        Qlmllll..7lq.................................................7ll......7..........q..7.....
7l        7qlllll7.q...................................................7ll[....[7...........[.[.....
77       ...7llllpq....................................................[llq....[............q.......
77      .....7lllV[.........................................[...........qll7...7............[.......
77Q    .......7ll7...................................[......7..........77lll...7.............7......
77V   q........q7.................................77.7......77..........7qllq.77.............[......
77V  V.........q......................7...........77.7[..7..77.[.........7lll777.7..................
73V  .........q......................[77..........77.77..7..777[...7.....7llmll[77..................
7mV q........7[................77....[l7..........77.77..77.[7777..7......7llll.77..[...............
lmlQ.........7.................77....7Q7.........[77.7q..77[77777[.77.[[.[.7llq.77..7...............
Qmll........7....[[............7[....pV7.........[77.7Q7[.77777777[77[777[.77777l7.77...............
lml........7....7............[7....7llq..[......777[7Ql[.77777777[[7[7777777777l7.77[..............
Qmlq......7....77............7q....7Q7l777...[..77777lQ7877777l7777777777777777l7.777..............
lll7.....7....77............77....lQ[p777...[..77q77lUl7.7777l777.77777777777ql7.777.........7....
77lll....77...[7[...[.......777...7Ul[7777...[..77l77lpQ777777ll77.77777[[7777lq7.777.........7[...
q..qll7...7....77...[.....[..7q7...7Q7[7777...7..7ql77l7Ul7.777ll77.77778.77777lp7.777.........77...
...[lll7.[7.[.[77...[.......77l7...ll[[7777...7..7ll77l[ll7.777lV777.7777.[[7777l7.7777........77...
....7lll777.7.7l7..7[.......77V7..7ll[.[p777..7..7ll77l[7lq7777qQl77.777[...7l77ll77777.7.7[..[77...
.....7lllq[77[7q7..7........77V7..7U7[..7777..7..7l777l.77l7..77Ul77.77[[...7l77ll777q777.77.[777..[
7.....7ll7.7.777..[7...[....77l7..7l[[..7777..7..7l777l[[777..[7ll77.77[[...l777lq777q777.77..777..[
7[...7..777777q7[.77.....[..lql7..lp[[..[p77..7.87l777p[[lpl7777ll77.7q[....l777ll777l7[7.77.[777[.[
.7..[77.777777l7..7........7lql7.7lp7qq..pq7..7.77l[777[.[7p777llpq7..l7...7l7777ll77l777.77.7777[77
7[..77.7777777l7..7........7llp77ql77[...7l77.7.77l[777[..777.77lql77.l7...777777ll77l7[7.77..777777
7..777.777777ll7.7[........qllp777l[[....[l77.7.77l[777[..77p787p77lq7q7...q777777q77l777..7.[[77777
..777..777777Rq7.7....7....llll7.77[[.....p77.7.77p[777[..[7p7.7p7777ql7...7.77777777l7.7..7.7[77777
[7777..77777ll7.77....7....lll77777[[.....7q7.7.77p[7p[[...[7777777677l7..77.7777l7l7l777..7.7777777
77q7..77777lll7.77..[.7...7llq77777[[......p77777p7[7p[[....[p7777[677ql..7..7777l777l7777.7.7777777
7777..77777l7l7.7...[.7...7ll77777[[[......777777l7[76[[.....77777[77777777..7777l777lm777[7.7777777
7q77..7777l77l7.7..7..7..7qll77777[[[......[77777l7.[7[.....[7p777[77777.q...7777l77qll777[7.7777777
q77...777ql77l7[7..7..7.777lp7777[.[[.......777777[.[q[..pQ  QQVl7.[7777.7...7777l77l7l777[7.77q7[77
V77..7777l77lq.7[.7..77.777lp7777..7lQQ p...777777[.[q...V Q     Qp[77l7.....7777l77l7l777[7.77q7777
Q7...777l777lq.7..7..7777[7lp77777l     V....q7777[.[7...qq.qV     Q77l7.....7777777m7l77777.77q7777
l7...77ml777l7.7.77..777.77l6777l    QQq7....q7777...[........VQQQ  Qll7.....7777777q7l77777.77l7777
q7..777l7777l777.77..777777q77[l  QQQQQl.....[777[............VQQQQQ  l7.....777777qqqlq7777.77l7777
l...77l77777l777.77..777777p7[p  qVQQQQQ......q77............7QQQQQQQ Q7.....7777ll7..ql7777777l7777
l..77ll77777l777777..777777l[7  q.l QQQQq.....7p[...........mVQQQQQQVQ l.....7777l..[.7l7777777l7777
q..7ql777777l777777..777777l[Q l..VQQQQQl......p............QQQQQQQQV7 Q.....77777.qp7[l777777qq7777
[.[ql7777.77q77777l..777777pq VqllQQQQQVV......[............QQQQQQQVV7Q 7....77777l7[7[p777777q77777
..7q77777.7777777lV7.777777qU 7q QQQQQRlV..................7QQQQQQRlQ7l l...77777ll77[[p777777q77777
..q77777..7777777VQ7.77ll77l U.7QQQQQQllQ..................qVllQQQlqQ77QQ...77777777[[[pp77777l77777
..7.77q7..7777777Q q.77ll77l l.7QlVQQQlqQ..................qVqlQVVlqQ77VQ7..77777[77[.[qq77777l77777
...777q7..777777q  q.77lU77l q.7VllQVQlpU..................7Q7qlll77Q777V7777777p7[[77.7777777lp7777
...777l7..777777l  l.77lVp7l 7.7V77lQl7lV................... q.....lQ.77l.777777l7[[77.77q7777ll7777
...77lQ77.777777V  V777VQp7pl...Q777q7.Vl...................l q..[l q.7qq.777777l7[[p[.q.q777qQl7777
...77V 77.77q777l  Q777lQ777q...VV....7 7....................l  Q  V.77l7777777ql777q.7q.ll77lQV7777
..77q  q7.77l77lq   777qQp7q7...7 Vqql V......................qVUUq..7777777777l[[77..p7.VQ77l Q7777
..77l  q7.77l77qq   l777Vl.7q....qQ   V.............................77777777777q.77..7q7.  77l  q777
..77V  lq[77777qq   V.77lQ..q[.....[[...............................7777777777q7[[..qq777  m7l  l777
..77   Vq777777qq   Q7q77Q7.7[.[[[...............[...............[.[7p[7777777q...ql7777l  V7V  Q777
777l   Vq77777lVl   Q7q77Qp.[[[[[[.................................[q7[777777lq..VV777q7Q  Q7Q   777
q77V   Qq7777qlQV   V7q77Ql..[[[[[.................................7p[[[q7777l7qQ l777q7    q    q7l
l77Q    l7777qUQV   l7q77ll........................................q7[.[p7777lq   l77qql    q    q8l
Q77     l7777qQ Q   lqq.77Q[.......................................q[..[l7777VlQ  l77lqQ    V    l.V
77     Q7777V      q7l.77 p......................................[7...[l777VQVQ  V77lq     Q    V.Q
q7      q777Q      q7l.77UQ7.................[[.......q..........[[...7l77VQ QQ  R77QV          V7Q
lq      l777       77q777pQQ7.................[.......................ql77    Q  Q7q            V7
Vq       777       ql7777q7QQq.......................................qU77l        7l            Qq
l       q77       lQ7.77q7l  V7...................................7V Q77         qV            Ql
V       V.q      VV 7.77l7V    Uq...............................7l   V7l         qV             V
7q      R  q[77QqV       Vq..........................qV     V7Q         VQ
qq         l777 qV          Vq[...................7lQ       Qq
ll         Q777 VV             Vp[..............qV          VV
QV          q7q VV                UVpq......[qVQQQ          V
V7l  V                    QVllVQQQQUQU          V
7l  V                 Q QQQQQQUllppql
lV                 VVlqlllUllppp667qpQ
Q                V.[q[.[77776ppppppqq7
VVV          V...q777[[[7qplqq[..q         Vqq[qV
Vq....7VVV     V..qq7[77qq77qq[.qr.q      Vq.......q
V..........q    V...vqq..q.qq.vv....q   q............q
..[.........q   V......v.vq.........qV V............[.V
q.......7....V V.qv......vvq........qq.VQq...........[.q
V.......7qqq77  q.........rrq.....qqqq..lQl...........[..
........q7777qlV..........qrq...vqqv....q V7qqq7......[..V
l........p7777777lqqqqqq..q[qq.........qqqlqq77q7.........q
.....[..[l77777777qq777qq.......7qqqqqllq7777777[.........[
V.....q..7l7777777777777777.7[7qqq7777777777777777..........
......7[.7l7777777777777777lq7ql7777777777777777qq..........q
......[7.ql7777777777777777q77777777777777777777qp...........V
q.......q[ql777777777qllllqq7777q7qqq777777777777lq....[.......
p........q77l7777777llQQQQQQlmlllVQQQQQRlll7777777l7.[.[[........
V.........[pql7777777lllllVQQRllllQQlllllllll77777ql777[q.........q
V...........qVl7777777777mlllllllllllllllll37777777ll7q[7...........q
V............7Ql777777777lll77mllllRm77lllm333777777lpp77[............V
V..............ll77777777ll777llllllll7777lll7777777ll777[..............