A better photo editor – its almost time!

We have so many photo editors, painting programs – but they all suffer from one big drawback. “None of them are good for common human”

It is almost time to completely change the direction of these photo editors, painting programs. We can improve their usability greatly by incorporating voice commands.

Anybody remember Star Trek Voyager Fair Haven episode and how Captain programs his holo-crush! Editing a photo or painting should be as easy as this.

A probable photo editing episode

Computer open my photo Gallery

<here you go…>

Select Third photo on second row.

<Here is your photo selected>

Let us edit this a bit

<OK>

Auto adjust

<I am applying auto improvements. How does this look?>

hmm.. Better. Save and Continue

<What else do you want to do?>

Crop by 75%

<Does this looks OK?>

No. that’s a lot, add 5% back.

<How about this?>

OK.

(You get the picture>

A Probable painting session

Computer ! Let us do some painting …

<OK, here is canvas>

Change background color to gray

<Done>

Paint two pairs of eyes.

<OK>

Make them green

<OK>

Insert two small clouds in those eyes

<OK>

Reduce the size of clouds by 75%

<OK>

Let the clouds rain

<OK>

Let the rain appear like tears dropping from eyes

<OK>

Save and Continue …

(You get the picture!)

Conclusion

The technology is already there. We just need to piece it together and productize it.

Solving Sudoku like humans do

.. is not difficult, but intriguing.

Usually solved with blind back tracking. But it felt soul-less. I want to solve like humans do.

Step 1: Solve each cell which can be guessed with 100% probability.

Step 2: Pick one of the available options and move to next.

Step 3: If nothing matches, back-track and change one of previous cells done in step 2. If reached start still nothing – no solution found.

The whole program is at https://github.com/chavakiranasdev/kichavaLibrary/blob/master/leet/hard/sudoku/Sudoku/Solution.cs

It is written and tested on Leetcode, so we ended up converting input to our object and reconverted back to required format.

CellState

/// <summary>
/// Represents state of single Cell. 
/// </summary>
internal enum CellState
{
    Empty, // Not yet filled. 

    InitialValue, // This value is already given 

    SolvedWithConfidence, // We found it with 100% probability. 

    InProgress, // Currently in progress. 
}

CellLocation

/// <summary>
/// Represents a single cell location. 
/// Used during backtracking to remember path
/// </summary>
internal class CellLocation
{
    public int Row { set; get; }
    public int Column { set; get; }
}

Cell

/// <summary>
/// Represents a cell 
/// </summary>
internal class Cell
{
    public CellState State { get; set; }
    public int CurrentValue { get; set; }

    // We tried this number & it is not fit here.
    // Used during backtracking to not re-use discarded values.
    public List<int> NotFitForThisCell { get; set; }

    public Cell()
    {
        State = CellState.Empty;
        NotFitForThisCell = new List<int>();
    }

    public void Reset()
    {
        CurrentValue = 0;
        State = CellState.Empty;
    }

    public void ClearNotFitForThis()
    {
        NotFitForThisCell.Clear();
    }
}

Find a match with 100% probability

// This checks if there is only one fit for this cell. 
// If it finds more than one fit, then we return zero.
private int GetBestFit(int row, int column)
{
    var gridKey = GetGridNumber(row, column);
    var availableInAllThree = rowAvailableList[row].Intersect(columnAvailableList[column]).Intersect(gridAvailableList[gridKey]);
    if (availableInAllThree.Count() == 1)
    {
        return availableInAllThree.First();
    }
    return 0;
}

Datastructures

// Constants 
// we can generally solve sudoku of any size. 
// So far, tested only for size 9
private int SizeOfSudoku { get; set; }

// Private variables. 
// Later, we create a board of given size (e.g.. 9X9)
private Cell[,] cellBoard;

// Next three dictionaries (hash's) represent each row, column, grid and still available values at any instance. 
// For example, once we initialize with input values, we remove them from corresponding row, column, grid. 
// Instead of three hashe's we could use 9X9 hashes to do same for each cell. That should be good for perf, for now this what I used.
Dictionary<int, List<int>> rowAvailableList = new Dictionary<int, List<int>>();
Dictionary<int, List<int>> columnAvailableList = new Dictionary<int, List<int>>();
Dictionary<int, List<int>> gridAvailableList = new Dictionary<int, List<int>>();

Constructor

public Solution(int sizeOfSudoku = 9)
{
    SizeOfSudoku = sizeOfSudoku;
    cellBoard = new Cell[SizeOfSudoku, SizeOfSudoku];
}

Solution

public void SolveSudoku(char[][] board)
{
    Console.WriteLine("Start...");
    InitializeAllAvailableLiistsWithEverything();
    // Initialize given char array into our cell array. 
    InitializeCellArray(board);

    // First round - find all those which doesn't need guessing.
    bool isAtleastOneBestFitFound;
    int currentRow;
    int currentColumn;
    do
    {
        isAtleastOneBestFitFound = false;
        // Solve each row. 
        currentRow = 0;
        while (currentRow < SizeOfSudoku)
        {
            currentColumn = 0;
            while (currentColumn < SizeOfSudoku)
            {
                if (cellBoard[currentRow, currentColumn].CurrentValue == 0)
                {
                    var bestFit = GetBestFit(currentRow, currentColumn);
                    if (bestFit != 0)
                    {
                        // We have a match. Update the cell with this value.
                        isAtleastOneBestFitFound = true;
                        UpdateCellValue(currentRow, currentColumn, bestFit, CellState.SolvedWithConfidence);
                    }
                }
                currentColumn++;
            }
            currentRow++;
        }
    } while (isAtleastOneBestFitFound);

    // Second round - Try to do best guess
    bool response = true;
    response = SolveByRow();
    if (response == false)
    {
        Console.WriteLine("Bug: Unable to solve given Sudoku");
    }

    // we should be done now. 
    // Just put final result into char array instead of cell object array
    for (int i = 0; i < SizeOfSudoku; i++)
    {
        for (int j = 0; j < SizeOfSudoku; j++)
        {
            board[i][j] = Convert.ToChar(cellBoard[i, j].CurrentValue + 48);
        }
    }
}

SovleByRow

 private bool SolveByRow()
    {
        bool response = true;
        if (!SolveGivenSubBlock(rowStart: 0, rowEnd: SizeOfSudoku - 1, columnStart: 0, columnEnd: SizeOfSudoku - 1))
        {
            response = false;
            Console.WriteLine("Bug? Unable to solve some of the grid");
        }
        return response;
    }

SolveGivenSubBlock

 private bool SolveGivenSubBlock(int rowStart, int rowEnd, int columnStart, int columnEnd)
    {
        bool response = true;
        for (int currentRow = rowStart; currentRow <= rowEnd; currentRow++)
        {
            for (int currentColumn = columnStart; currentColumn <= columnEnd; currentColumn++)
            {
                if (!SolveGivenCell(currentRow, currentColumn))
                {
                    response = false; // do not overwrite this value for next cell's success, and thus above if
                }
            }
        }
        return response;
    }

SolveGivenCell

  private bool SolveGivenCell(int currentRow, int currentColumn)
    {
        bool response = true;
        var currentCell = cellBoard[currentRow, currentColumn];
        if (currentCell.CurrentValue == 0)
        {
            // go back tracking. 
            // This will first attempt to find best guess if not found then back tracks.
            if (!BackTrackRealThisTime(currentRow, currentColumn))
            {
                response = false;
                Console.WriteLine($"Bug? Unable to solve {currentRow} :: {currentColumn}");
            }
        }
        return response;
    }

Backtracking

 private bool BackTrackRealThisTime(int currentRow, int currentColumn)
    {
        var stack = new Stack<CellLocation>();
        // clear not fit for this, if any from prevous attempts.
        cellBoard[currentRow, currentColumn].ClearNotFitForThis();
        stack.Push(new CellLocation() { Row = currentRow, Column = currentColumn });

        while (stack.Count != 0)
        {
            var currentTopOfStack = stack.Peek();
            var bestGuess = GetBestGuess(currentTopOfStack.Row, currentTopOfStack.Column);
            if (bestGuess != 0)
            {
                // We have a guess. Update the cell with this value.
                UpdateCellValue(currentTopOfStack.Row, currentTopOfStack.Column, bestGuess, CellState.InProgress);
                stack.Pop(); // Remove this from stack.
                continue;
            }
            var previousCellLocation = GetPreviousInProgressCellLocation(currentTopOfStack);
            // Push this cell onto stack after emptying it.;
            var previousCell = cellBoard[previousCellLocation.Row, previousCellLocation.Column];
            previousCell.NotFitForThisCell.Add(previousCell.CurrentValue);
            RemoveCellValue(previousCellLocation.Row, previousCellLocation.Column);
            // Now that we are moving further back, current cell's notfit is no longer valid.
            cellBoard[currentTopOfStack.Row, currentTopOfStack.Column].ClearNotFitForThis();
            stack.Push(previousCellLocation);
        }
        return true; // stack is empty
    }

Conclusion

I tried to be lazy and backtrack in random, without remembering path – but on my machine it works, leetcode always timed out. Forcing me to be a better 🙂

Get rest of the code from above github link.

Notes while becoming a Gopher (aka learning Go language)

  1. Functions returning multiple values is taken to next level.  
  2. Golang’s documentation to get started is very well designed and implemented. Other languages can learn a bit from here to not make their complex-language learning extra-complex.  
  3. I thought I have seen last of pointers for major use cases, alas, I am mistaken.  
  4. “for” is new ‘while’.  
  5. Switch is all powerful.  (Good. I still remember how I suffered with switch in Java6 days)
  6. Methods are c# extension methods. (Or the otherway)  
  7. Go is C.Redefined. (Or C.Redesigned or C.Improved)  
  8. Go is not OOPS but Go is OOPS (Or Go is only a bit of OOPS and lot of Procedural)  
  9. Copy is actually CopyTo as destination is first argument and source is second argument.  
  10. Defer will do finally’s job, in more human way. Defer + Recover is catch; panic is throw exception. But the documentation says they don’t have try catch – I am a bit confused. It feels panic-defer-recover are more human friendly design of try-catch-finally.
  11. I may miss c#’s $_ string interpolation. 
  12. Loved separate name for rune. Makes conversing in Unicode characters more straightforward. 

An idea to save Twitter from itself : InDoor

Twitter is great – for celebrities, media and folks inside media.

But for common-man twitter is chaos. Nothing much to offer for them other than keeping up to date which also not possible due to its infinite chaos. Even if one follows ten people, it is impossible to feel satisfied. It is always unfinished – forcing people to run away to other social networking sites or moving on with life.

One idea to save Twitter from this self destructing nature. InDoor

Allow people to make their own twitter.

  1. Anybody can create an indoor twitter.
  2. Example twitter.com/indoor/myFamily or twitter.com/indoor/myTeam
  3. Tweets inside indoor are for members only.
  4. Every member follows every other member by default this setting can be changed either globally or per member by moderator.
  5. One can unfollow any member.
  6. One can retweet public tweets to indoor only.
  7. Once on indoor there won’t be any confusion whole twitter interface remains same, except everything now applies to indoor account. Users can easily exit indoor and go to public twitter.

This should make twitter more useful to common members who are not celebrities. This will put twitter in direct competition with What’sapp for family/friend groups + slack/teams for office groups.

Once basic structure is there – we could go on innovating much more.

Taming the horse

Once upon a time, 
there was a rider -
who bought a horse,
Failed to tame it - 
shot it in the end.
Bought another horse, 
this time left it to wild.
After several dead and
multiple feral horses -
it flashed to him -
It is not he who is trying to tame -
rather the horses are testing him.
he failed them miserably.
He no longer needed to tame any - 
Now he could ride any horse.

It never gets old,

 It never gets old, 
The king camping around enemy fort, 
me, taking care of business usual here. 


Every Friday - 
I wait for the rider with news,
Are the gates opened? 
Or the walls fallen? 


A poem from the king, 
Is the sole reason for me,
Not to go mad in this role
Of queen in waiting. 


He talks about everything, 
Except the war. 
The food, mostly stale - 
The weather, mostly dull - 
The tents, mostly gray - 
Yet, it brings out best of me.


For the people, 
I am the queen. 
For the King,
I am the trusted, 
For the palace, 
I am the supreme. 
For me - 
Who am I? 



Circular script – A daring redesign of script for modern humans.

After watching for Arrival, I had this creative urge to design a circular script for humans. This could be used like a human-readable QR code. Current QR codes are only readable by computers, how about having all the benefits of QR code + making it human readable too!

On Nov 11th 2016 1:50 PM EST this is what I wrote in a notebook purchased at Miami airport.

Circular Script.

Background: Today I watched Arrival film along with Katta.Vijay in Miami. In that movie aliens uses a circular script with very complex form to represent words, ideas and even sentences.

Then it occurred to me, if we can use the same circular script to write human languages we could save lot of space. In one circle we could write one letter or one word or partial word or multiple words. By saving space we could make reading even faster.

Goals of new script:

Goal 1: It must be on, around circle.

Question: Why not square or rectangle or triangle or spiral?

Answer: It could be on any of them. So the circular script designed will be easily usable, portable onto any other geometric shape. Over time users will stick to one or more of these shapes.

Goal 2: Symmetry :-> The script should be symmetrical in more than one ways.

Goal 3: Script must be easy to write.

Goal 4: Script must be easy to read.

Goal 5: Script must be easy to learn.

One of the biggest advantages of Latin alphabet is it is damn simple to learn. Kids, adults as first language script or second language script it is easy to learn. Of course there are historically done research and tool development to make this possible.

Goal 6: Script must be readable even if circle rotates.

Goal 7: Script must be independent of thickness of line. Making it bold, bolder, boldest must not change its meaning.

Goal 8: Script must be independent of size. Making it large or small should not change the meaning. Of course making it smallest could make it unintelligible.

Goal 9: Script must allow artistic liberties.

Goal 10: Filling or un-filling a shape must not change its meaning. For example O and O with inside also filled dark holds same meaning.

Goal 11: Redundancy is allowed.

Goal 12: The alphabet (not word) must be same irrespective of the direction we read it. for example

Goal 13: Color must not change meaning.

Goal 14: By keeping two letters next to each other it must not give another letter. It must be same letter twice.

Goal 15: Squares and rectangles must be considered as same letter. Similarly for other shapes.

Goal 16: The mirror image must not give another letter. But it could be different shape representing same letter.

Goal 17: By putting two same or different letters side by side without anybody gap must not give us different letter. even the mirror image.

Goal 18: A curve and line must be treated same. Doesn’t apply to half circle.

Goal 19: The shape must be complete. can not be open. They must be Purna.

Even if they are not complete, it must not become different letter once completes.

This is still incomplete project ….

A nightmare

We landed on this planet, 
Under this turquoise sky,
With flying tangerine leaves,
Slept on mantis beds.

All of a sudden,
A screeching sound thousand-fold,
Surrounded by dark crows,
Was awake to feel every pinch,
Was asleep to make any moves,
A dreary dark nightmare.

I see a witch in white drape,
trying hard to wake me up.

I see humming birds,
trying hard to break the crow cloud.