Android App ep.102

My Network Reporter v.2

For this project we are going to be recreating the network reporter application in Kotlin to look at the advantages and uniqueness Kotlin can provide.

Previous application utilizing java: Android App ep.101

Application Purpose:

This will remain the same as the last application….

We want to discern if transmitting a file of a size A across a network with a speed B gives us a reasonable time in seconds.

Our size of the file size is measured in MiB and our network speed is measured in Mbps.

We know that 1 B = 8 b; 1 MiB = 220 B; 1 Mbps = 106 bps.

Video to view in action: https://youtu.be/JUkxk5NhutM

activity_main.xml  Layout


This will remain the same as well since we just want to look at the benefits of Kotlin to Java.

Screen Shot 2018-10-15 at 8.44.27 AM

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textView"
        android:layout_width="96dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingHorizontal="10dp"
        android:text="@string/file_size_label"
        android:textAlignment="center"
        android:textAllCaps="false"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/fileSizeInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/file_input_hint"
        android:inputType="number" />

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/networkSpeedLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/network_label"
        android:textAlignment="center"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/networkSpeedInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/network_hint"
        android:inputType="number" />
</LinearLayout>

<TextView
    android:id="@+id/resultDisplay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Input is needed for both File Size and Network Speed to estimate time"
    android:textAlignment="center"
    android:textColor="@android:color/black"
    android:textSize="18sp" />

On our Kotlin side…


package com.amsuarez.mynetworkreporter

import android.app.Activity
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    fun EditText.changed() {
       this.addTextChangedListener(object: TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
            override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
                if (fileSizeInput.text.toString() == "" || networkSpeedInput.text.toString() == "") {
                    resultDisplay.text = "Input is needed for both File Size and Network Speed to estimate time"
                } else {
                    val myb = Integer.parseInt(fileSizeInput.text.toString()).toDouble() * Math.pow(2.0, 20.0) * 8.0
                    val mybps = Integer.parseInt(networkSpeedInput.text.toString()) * Math.pow(10.0, 6.0)
                    resultDisplay.setText(String.format("%.1f", myb / mybps) + " seconds")
                }
            }
            override fun afterTextChanged(s: Editable) {}
        })
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fileSizeInput.changed()
        networkSpeedInput.changed()
    }
}

Here we utilized some really cool features that Kotlin provides us with.

Extension Functions:

We utilized these to extend upon the EditText class to allow us to run a text watcher object in any EditText. This gives us a very clean call in our onCreate fun increasing readability.

Where are the findViewByIds? 👀

Kotlin provides a feature that allows us to reference straight out of our activities.

It is done by importing:

 import kotlinx.android.synthetic.main.activity_main.*

This allows us to no longer need to call findViewById and instead we can reference directly into our activities.

Objects? 🤔

Here we use object as an anonymous class that inherits TextWatcher allowing us to override the TextWatcher without having to “formally declare a new class”.

For more on Objects: https://kotlinlang.org/docs/reference/object-declarations.html

 

Android App ep.101

 

My Network Reporter

For this project we are going to be creating a simple application using TextFields, EditText, and a TextWatcher.

This tutorial assumes you know basic information about widgets and Java programming

Application Purpose:

We want to discern if transmitting a file of a size A across a network with a speed B gives us a reasonable time in seconds.

Our size of the file size is measured in MiB and our network speed is measured in Mbps.

We know that 1 B = 8 b; 1 MiB = 220 B; 1 Mbps = 106 bps.

Video to view in action: https://youtu.be/JUkxk5NhutM

activity_main.xml  Layout


Screen Shot 2018-10-15 at 8.44.27 AM.png

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textView"
        android:layout_width="96dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingHorizontal="10dp"
        android:text="@string/file_size_label"
        android:textAlignment="center"
        android:textAllCaps="false"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/fileSizeInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/file_input_hint"
        android:inputType="number" />

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/networkSpeedLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/network_label"
        android:textAlignment="center"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/networkSpeedInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/network_hint"
        android:inputType="number" />
</LinearLayout>

<TextView
    android:id="@+id/resultDisplay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Input is needed for both File Size and Network Speed to estimate time"
    android:textAlignment="center"
    android:textColor="@android:color/black"
    android:textSize="18sp" />

Here we kept it as simple as possible using two linear layouts to block each input and label and a separate TextView to display a result.

 

On our Java side…


public class MainActivity extends AppCompatActivity {
    EditText fileSize;
    EditText networkSpeed;
    TextView result;

     // Here we use a TextWatcher to see if there are any changes.
    TextWatcher watchChange = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if(fileSize.getText().toString().equals("") || networkSpeed.getText().toString().equals("")){
                result.setText("Input is needed for both File Size and Network Speed to estimate time");
            }
            else {
               // this section calculates the time to send.
                Double myb = Integer.parseInt(fileSize.getText().toString()) * Math.pow(2, 20) * 8;
                Double mybps = Integer.parseInt(networkSpeed.getText().toString()) * Math.pow(10, 6);
                result.setText(String.format("%.1f", myb / mybps) + " seconds");
            }
        }
        @Override
        public void afterTextChanged(Editable editable) {}
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

         // this section assigns our java code to the xml android widgets
        fileSize        = (EditText) findViewById(R.id.fileSizeInput);
        networkSpeed    = (EditText) findViewById(R.id.networkSpeedInput);
        result          = (TextView) findViewById(R.id.resultDisplay);
        
        //this assigns the TextWatcher to both entry fields
        fileSize.addTextChangedListener(watchChange);
        networkSpeed.addTextChangedListener(watchChange);
    }
}

For more on TextWatchers visit Android documentation here : https://developer.android.com/reference/android/text/TextWatcher

Medium: Article: https://medium.com/@austinmsuarez/android-app-ep-101-83e0f0af8aa0

Mancala-AI

Mancala-AI

By Matt Corrente, Paul Miller, Luigi Sanchez, and Austin Suarez

Project Link: https://github.com/138paulmiller/Mancala-AI-Bot/blob/master/README.md

Summary

The Mancala AI is a project that I got to work on with some very talented programmers (Matt Corrente, Paul Miller, and Luigi Sanchez). Our project was to use artificial intelligence in a unique way. Although AI for games has been done we thought it would be interesting to do a study on how each AI algorithm can compete against one another. We built out it out three different AI algorithms ( Min-max with Alpha beta, Monte Carlo, and Evolutionary) to run on a Flask app.

About Mancala

“It’s an ancient family of board games, and there are numerous variants. Many different forms of Mancala are played across Africa, though the game may originally have come from ancient Sumeria.”[1]

Mancala is a two player turn-based board game.The goal is to capture the most beans and stones into your side.

Since Mancala is a game with a clear set of rules it allows for each AI to calculate a path to victory fairly. By fairly, we mean that some variations of this game are not perfect and allow for an extremely calculate the first move that is capable of ending the game.

 

Rules

  1. The Mancala board is made up of two rows of six holes, or pits, each.
  2. Four pieces—marbles, chips, or stones—are placed in each of the 12 holes.
  3. Each player has a store (called a Mancala) to the right side of the Mancala board.
  4. The game begins with one player picking up all of the pieces in any one of the holes on his side.
  5. Moving counter-clockwise, the player deposits one of the stones in each hole until the stones run out.
  6. If you run into your own store, deposit one piece in it. If you run into your opponent’s store, skip it.
  7. If the last piece you drop is in your own store, you get a free turn.
  8. If the last piece you drop is in an empty hole on your side, you capture that piece and any pieces in the hole directly opposite.
  9. Always place all captured pieces in your store.
  10. The game ends when all six spaces on one side of the Mancala board are empty.
  11. The player who still has pieces on his side of the board when the game ends capture all of those pieces.
  12. Count all the pieces in each store. The winner is the player with the most pieces. [2]

Algorithms

Mancala represents a decision problem since each player must decide on a single move to make. Each of our AI agents makes use of varying algorithms for decision making.

We used:

  • Minimax with Alpha-Beta Pruning
  • Monte-Carlo Tree Search
  • Evolutionary Algorithm with binary encoded moves

The algorithms we used vary in the method of deciding. For example, our Minimax, Monte-Carlo and Evolutionary algorithms make use of traversing the current game tree. However, both searching algorithms use different heuristics to limit the state space being search. The state space for an entire game is very large, and running an exhaustive search on the entire game tree will run in about O(6^n) time. Where n is a number of total turns, where each player has at most 6 choices. A naive exhaustive searching algorithm for this is completely inefficient, so adding a maximum lookahead depth allows us to bound the search space for our algorithms making them run in a reasonable enough time to play against.

 

Heuristics

All our algorithms make use of a variable heuristic function. This function analyzes the current state of the board to help the AI make the best possible decision. This heuristic can be used to:

  • Maximize AI’s score
  • Maximize the difference between the AI and players score
  • Maximize the number of pebbles on the AI side
  • Maximize the difference between the number of pebbles on AI side from player’s side

Or a weighted polynomial of the above (x = score, p = pebble diff = x+p*0.3)

Modifying the evaluation heuristic also changes the difficulty of the AI. For instance, in the Minimax algorithm, evaluating the score performs much better than evaluating a number of pebbles on each side. Also, measuring the relative score between the player and the AI performs better than just maximizing the AI. The reasoning behind this would be that the AI not only maximizes his own score but also makes sure that the next best move for the player will be far lower than the AI’s score. So, it would preference 9 vs 3 over 10 vs 8.

 

Playability

Each of our algorithms performs differently. The Minimax algorithm with Alpha-Beta pruning is a more exhaustive searching making it much slower but is also much more difficult to beat. With a turn lookahead depth of around 6-8, the AI is quick enough to play and very difficult to beat. However, if the lookahead is not set and the AI searches the entire game tree, the AI will be unbeatable, however, due to the time complexity of the game tree, the AI takes far too long to decide on a move even with alpha-beta pruning. So, both Monte-Carlo and Evolutionary Algorithm decision-making approaches are much more user-friendly. The Monte-Carlo algorithm makes uses of a probabilistic adversarial decision making, which chooses the other players most likely move. This allows the algorithm to be far less exhaustive making it capable of making more human-like decisions, since the enemy may not always choose the predicted move. The Evolutionary algorithm makes use of binary programs that encode possible moves for the AI. The populations are initialized randomly and evolved using probabilistic mutation and crossover. Each population is evaluated by testing the heuristic for each next potential move, and the moves with the highest scores are more likely to be chosen for reproduction.

Conclusion

This was a very interesting project. Since the game tree is simple enough to visualize, yet results in an exponential explosion of possible game states. Each AI plays the game differently thus it is very interesting to see the result from the AI vs AI.

Work Cited

[1] https://www.thespruce.com/how-to-play-mancala-409424

[2] https://www.thespruce.com/how-to-play-mancala-409424

Deck of Cards Trick

Here is a great critical thinking problem that I heard.

Scenario:

You are blind folded and cannot see.

I hand you a deck of cards telling you that a 5 are faced up and placed randomly in the deck (the rest are face down)  and ask you to split the group of cards into two groups such that each group has the same amount of face up cards.

This problem is great because one it forces you to think outside of the box and since the question itself can be easily represented in a computer science context.

 

(please try before just looking at solution, there is a way to split with 100% accuracy)

WARNING SPOILERS  SOLUTION BELOW!!!! 

 

 

 

Explanation:

The amount of cards in the deck doesn’t matter nor does the position of the cards face up in the deck. We can represent the problem as an array with 1s (face up ) and 0s (faced down). We can assume that based on the questions the groups don’t need to have the original amount of face up cards (5 is odd and you can’t really split it up evenly). Thus we must think how can to place the two groups separately.  If you take the amount of flipped cards from anywhere in the deck and invert them no matter their current orientation and take them placing it into group one and the rest into group two you will have met the problem conditions and have the correct solution.

#include <iostream>
#include <random>

using namespace std;
 //Compiler version g++ 6.3.0

int main()
 {
 	int deck[52];
 	int temp;
 	int flipCards = rand()%52+1;

	int* groupOne;
	int* groupTwo;

	for(int index =0; index < 52; index++)
 	{
 		deck[index] = 0;
 	}
	for(int index = 0; index < flipCards; index++)
	{

		do{
 			temp = rand()%52;
 		}while(1 == deck[temp]);
 		deck[temp]=1;
 	}
	groupOne = new int[flipCards]();
	groupTwo = new int[52-flipCards]();

	for(int index =0; index < 52; index++)
	{
		cout << deck[index] << endl;
	}
 	cout << endl;
	for(int index = 0; index < flipCards; index++)
 	{
		deck[index]= abs(deck[index]-1);
		groupOne[index] = deck[index];
 		cout << groupOne[index];
	}
	 cout << endl;

	for(int index = flipCards; index < 52; index++)
	{
		groupTwo[index] = deck[index];
 		cout << groupTwo[index];
 	}
 	cout << endl;
	return 0;
 }

Electronics Shop

This Hackerrank problem deals with combinations.

The problem:

Sketch

import sys

def getMoneySpent(keyboards, drives, s):
 combo = -1
 for k in keyboards:
 	for d in drives: 
 		if (k+d) > combo and (k+d) <= s:
 			combo = k+d
 
 return str(combo)
 
s,n,m = input().strip().split(' ')
s,n,m = [int(s),int(n),int(m)]
keyboards = list(map(int, input().strip().split(' ')))
drives = list(map(int, input().strip().split(' ')))
# The maximum amount of money she can spend on a keyboard and USB drive, or -1 if she can't purchase both items
moneySpent = getMoneySpent(keyboards, drives, s)
print(moneySpent)

This problem is pretty straight forward. I used to for loops to cycle through each list.

Another way to do it might be to sort the list eliminate the clearly overly expensive items that are over s and delete those that are  duplicates to cycle through less elements. This might help for very big lists.

 

The Day of the Programmer

This Hackerrank problem asks you given the year, the 256 date of that year according to the Russian Calendar.

Screen Shot 2017-11-05 at 5.35.44 PM

The Code:

import sys

def solve(year):
    months = [31,28,31,30,31,30,31,31]
    
    if year > 1918:
        if year%400 == 0 or (year%4 == 0 and year%100 != 0):
            months[1] = 29
            tmp = sum(months)
            day = 256-tmp
        else:
            tmp = sum(months)
            day = 256-tmp
    elif year == 1918:
        months[1] = 15
        tmp = sum(months)
        day = 256-tmp
    else:
        if year%4 == 0:
            months[1] = 29
            tmp = sum(months)
            day = 256-tmp
        else:
            tmp = sum(months)
            day = 256-tmp
    

   return (str(day) + '.' + "09" + '.' + str(year))
year = int(input().strip())
result = solve(year)
print(result)

For this problem, I set the number of days in the months from January through August into an array and summed them together. After which I subtracted from 256 and got the day. To get the variations in days I altered the month of February based on the calendar system.

Developer Aside:

I took the easy way out in displaying the month since in the Russian calendar system (regardless of the year) the 256 day lands in September.

 

Kangaroo

This is another easy Hackerrank question, Kangaroo.

This problem takes a high school math problem of will one car ever catch another, but instead of cars we are talking kangaroos

kangaroo

def kangaroo(x1, v1, x2, v2):
 if x1 > x2:
    temp = x1
    x1 = x2
    x2 = temp
    temp = v1
    v1 = v2
    v2 = temp 
 
 if v1 <= v2:
    return "NO"
 
 while(x1 < x2):
    x1+=v1
    x2+=v2
 if(x1 == x2):
   return "YES"
 else:
   return "NO"

#given
x1, v1, x2, v2 = input().strip().split(' ')
x1, v1, x2, v2 = [int(x1), int(v1), int(x2), int(v2)]
result = kangaroo(x1, v1, x2, v2)
print(result)

For this problem I set x2 to always be further than x1 by creating a swap condition. After I check if the kangaroo at x1 has a velocity higher than kangaroo at x2 if it isn’t they will never meet. Finally I cycle through until x1 is no longer less than x2.

Apple and Orange

I have been applying to different internships lately and have been referred to hackerrank through many of them so I decided why not add and talk about my solutions to some of the challenges.

This problem is called Apple and Orange and the whole point is to print the number of apples and oranges that fall from Sam’s house.

Here is the problem:

appleOrange

#!/bin/python3

import sys

#given

s,t = input().strip().split(' ')
s,t = [int(s),int(t)]
a,b = input().strip().split(' ')
a,b = [int(a),int(b)]
m,n = input().strip().split(' ')
m,n = [int(m),int(n)]
apple = [int(apple_temp) for apple_temp in input().strip().split(' ')]
orange = [int(orange_temp) for orange_temp in input().strip().split(' ')]

#my code

count = 0
for ap in apple:
     temp = a+ap
     if temp <= t and temp >=s:
         count = count + 1 
print (count)

count = 0
for ora in orange:
    temp = b+ora
    if temp <= t and temp >=s:
         count = count + 1 
print (count)

This problem is fairly simple I used two for loops since the array size for apple and orange can differ and I had to print the total apple and total orange.

 

Mental Note

Mental Note was a note taking application (also the first UWP)  I built. I wanted to try and understand MSA login and async file storage. It was a fun little side project, there are definitely some bugs and design choices I would do differently now. In the end I walked away understanding the ideas of login and file storage for UWP applications.

The project is in my GitHub: GitHub.com/amsuarez01

Here are some screen shots.

This slideshow requires JavaScript.

Habit Hamster

Habit Hamster is a application that will keep track of habits like a reminder list. Current habit tracking apps do not provide a means for users to visually see progress. I am currently working on this in my Software Engineering class and am loving how awesome it is to make UWP applications.

It is currently on my GitHub: GitHub.com/amsuarez01 under Habit hamster.

Here are some Screen shots of the UWP side of development that I have been in charge of.

This slideshow requires JavaScript.