Thursday, August 16, 2018

Coding for fun: Roman Numeral Converter with unit tests

I was listening to an audiobook this morning about the evolution of communication technology. It's The Information by James Gleick. Good book. I should probably write a longer review later. For now though, I happened to hear a section where Claude Shannon amused himself by writing an early program that translates Roman numerals. I figured if it's good enough for Shannon, it's good enough for me, although I have better tools that make it easier. So anyway, just for fun:

Conversion class:

package com.russellglasser.romannumeral;
import java.util.HashMap;
import java.util.Map;

class RomanNumeralConverter {

   private final String[] romanDigits;
   private final Long[] arabicDigits;
   private final Map toArabicTable;
   private final Map toRomanTable;

   RomanNumeralConverter() {
      romanDigits = new String[]{"M", "CM",
            "D", "CD", "C", "XC",
            "L", "XL", "X", "IX",
            "V", "IV", "I"};
      arabicDigits = new Long[]{1000L, 900L,
            500L, 400L, 100L, 90L,
            50L, 40L, 10L, 9L,
            5L, 4L, 1L};
      toArabicTable = new HashMap<>();
      toRomanTable = new HashMap<>();
      for (int i = 0; i < romanDigits.length; i++) {
         toArabicTable.put(romanDigits[i], arabicDigits[i]);
         toRomanTable.put(arabicDigits[i], romanDigits[i]);
      }
   }

   String toRoman(Long arabic) {
      StringBuilder builder = new StringBuilder();
      Long remaining = arabic;
      for (Long digit : arabicDigits) {
         while (remaining >= digit) {
            builder.append(toRomanTable.get(digit));
            remaining -= digit;
         }
      }
      return builder.toString();
   }

   Long toArabic(String roman) {
      String remaining = roman;
      Long result = 0L;
      for (String digit : romanDigits) {
         while (remaining.startsWith(digit)) {
            result += toArabicTable.get(digit);
            remaining = remaining.replaceFirst(digit, "");
         }
      }
      return result;
   }
}
Unit test class:

package com.russellglasser.romannumeral;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class RomanNumeralConverterTest {

   private final RomanNumeralConverter converter = new RomanNumeralConverter();

   @Test   void toRoman1() {
      check(1L, "I");
   }

   @Test   void toRoman3() {
      check(3L, "III");
   }

   @Test   void toRoman4() {
      check(4L, "IV");
   }

   @Test   void toRoman8() {
      check(8L, "VIII");
   }

   @Test   void toRoman14() {
      check(14L, "XIV");
   }

   @Test   void toRoman18() {
      check(18L, "XVIII");
   }

   @Test   void toRoman1979() {
      check(1979L, "MCMLXXIX");
   }

   @Test   void toRoman2018() {
      check(2018L, "MMXVIII");
   }

   @Test   void toRoman9999() {
      check(9999L, "MMMMMMMMMCMXCIX");
   }

   private void check(Long arabic, String roman) {
      assertEquals(roman, converter.toRoman(arabic));
      assertEquals(arabic, converter.toArabic(roman));
   }
}

Tuesday, August 2, 2016

Tech talk about Pokemon Go



Quick background for people who don't already know: Pokemon Go is a mobile game that launched last month on Android, and more recently on iPhones. It is billed as an "augmented reality game," in that the gameplay incorporates a requirement to walk around in the real world and visit physical locations, and some virtual objects are treated within the game as if they physically exist at those locations. It was immediately popular, and has been plagued with ongoing problems with server response and performance. In this post I will discuss these issues on a level that laymen should be able to understand.

Friday, February 12, 2016

Techie Rant: Mobile apps shouldn't override web browsers

Dear Facebook:

I would like to politely offer feedback on this "instant article" feature that you are so proud to have updated on my mobile device.

I don't want to have to read long articles in the Facebook mobile app.

I don't EVER want to have to read long articles in the Facebook mobile app.

Thursday, January 14, 2016

Thanks for the help, cloud AI!

This is just a quick silly story that illustrates how the "intelligent" programs that monitor our lives can be both funny and creepy.
At my work, we have an intranet application -- something that runs in a web browser, but it's only visible from inside the office -- which tracks change requests and bugs we are working on. I am on the Client Account team, so most of my projects are identified with "CA-" and then a number, such as "CA-1234."
Usually after I have been working on one project for a while, I have memorized the number, and so I just type "CA-1234" into my browser. Since I have visited the feature page often, it automatically fills in the URL to take me there. But sometimes I mistype, or it doesn't work for some other reason, so my browser helpfully pulls up a Google search for CA-1234 instead.
That does not contain any information that is useful to me. However, it does often match a flight number on China Airlines.
So one morning I got an alert on my Android. It was Google's calendar program. It told me "It's time to leave for the airport if you want to catch that flight on China Airlines that you looked up!"

Tuesday, October 27, 2015

Advice for aspiring software engineers

I went for my Master's Degree after living in Austin for several years and working at a low level programming job at a large company. I felt really stuck. The nature of my work hadn't changed significantly in many years, and my team wasn't even trying to keep up with new technology. I was bored and didn't see things changing.

When I completed my degree in 2008, I was now overqualified for my job, but I also lacked the experience to get the kinds of jobs I was aiming for. The economy was also a disaster. I bounced around a number of contract jobs for several years, not managing to get a reliable permanent job until 2011. Three years later, I got a call from a recruiter at Blizzard Entertainment, a company I've been a big fan of since I played Warcraft II in college. I went through two lengthy interviews and joined the web development team. I'm pretty happy with the track my career has taken.

Last December, my cousin David wrote to me on behalf of a friend in college who wanted to know how he should proceed in order to make himself attractive to employers and land a decent job. I sent him the advice below. Due to the nature of my online media activities, a lot of young people write to me with similar questions, so I thought I'd recreate the advice for everyone to read.

Friday, November 14, 2014

Explain like I'm five: DDoS attack

A friend of mine asked me to literally "explain like I'm five" how a DDoS (Distributed Denial of Service) attack works, because World of Warcraft was having troubles yesterday after the launch of Warlords Of Draenor, and he was trying to tell his kid why. My answer:

When you play Warcraft, the computer that represents you is always "talking" through the internet to the computer that has everything in the WoW world. Computers have a limited attention span; they can talk to a lot of people at the same time, but not everybody in the world.

Usually they have enough attention to talk to all the people who are trying to play WoW at the same time. But sometimes bad people don't want the game to work right, so they pretend to be a million people and all try to talk to the computer at once. The world computer doesn't know who's a real person and who's not, so it gets confused and talks to all the million fake people. Then it doesn't have time to talk to you, so the game goes slow because it can't send you information about what's happening fast enough.

Sometimes people do this because they're mad at the company, and sometimes just because they think it's funny. It's against the law, but it's hard for the police to understand, so usually the company that is getting attacked has to deal with it on their own.

Wednesday, February 12, 2014

Adventures in junior programming, episode 4

As I've mentioned in previous posts (1, 2, 3), I've been teaching my son Ben a little Python here and there over the last few years. We're not very consistent, and in fact we haven't really done it much at all in a year or so. But that's not too terrible; it sort of reflects my own experience at Ben's age. I tinkered a little bit with BASIC once in a great while, copied some programs out of books and magazines, "hacked" some programs, forgot many things, and didn't really get deeply into program structure at all until I reached high school. So this is not an urgent task for me.

Ben and I did some work over the weekend. I have taught him a few things over the last couple of years, but we do it so sporadically that it's hard to keep the information fresh in his mind. So we started with this exercise: opened several of the programs that he has worked on in the past, then read through each one and predicted what it was going to do, and why. Doing this helped him get back into his headspace from earlier sessions, and also drilled the syntax back into his mind pretty quickly. Speaking for myself, I also find that reading my own code can help to refamiliarize myself with a language much more quickly than reading somebody else's examples.

Up until now it was clear that we'd done a lot of programs that were really brief -- single problem, single solution. Print all the powers of two up to a million. Print out a times table. Create a simple password verification program (which insults you if you fail; that's a ten year old mindset for you). These problems are interesting in their own right, but the real fun of programming is making a project with no immediate end goal, something you can tinker with over a long period.

Ben is very into gaming, just like his dad. We've been playing World of Warcraft together since he was seven. This seemed like a promising starting point, so I had him create a simple system of rules which could represent a fight between a hero and a monster. So we started out with a few basic hard coded numbers: Hero hit points, monster hit points, hero damage value, monster damage value. Then we wrote a loop so that the fight would keep going until one of the hit point values dropped below zero.

The program is pretty predictable at this point; the beauty of the concept is that we can build on the basic concept over time. So the first thing Ben wanted to do was tweak the numbers: The hero should always win, but just barely. So we did some math to figure out how to make that happen, and we saw the outcome change as the starting values got closer to numbers that "felt right."

This was a good time to introduce functions, which I don't think I've explained in detail before. We had a function for printing the current status ("The hero has X hit points! The monster has Y hit points!"); a function called "hithero" and another called "hitmonster". Initially the hit functions removed a fixed amount of damage; then we got a little more sophisticated, passed in the damage as a parameter, and also printed the action to the screen. After that we also added in weapon descriptions, so it then said "The hero hit the monster for 20 damage with his sword of epicness!"

It's a fun exercise and it has Ben's enthusiasm up, so he now thinks of it as "The first program I wrote mostly by myself!" (I did give him a whole lot of guidance, actually, but I've let him steer the creative direction of the program, so he does have plenty to be proud about.)

We now have a bug and feature wish list which is surely going to grow:
  • Make it so hit points can't go negative.
  • Make a "death" message.
  • Have multiple kinds of weapons; enable weapon switching.
  • Randomize damage within a range, like 16-24.
  • Allow the hero to pick a type of action, a la Pokemon, such as a direct damage attack or a debuff attack.
  • At some point we should probably start discussing object-oriented programming, before we get to the point where we bring in multiple monsters.
  • Item drops?
  • Visiting locations?
  • Ben really wants to make graphics, but that is a very advanced topic, and I'd rather he get solid with the fundamentals before touching that one.
  • I'm a web programmer, and putting stuff in web pages is a great way to showcase your work to friends. So maybe that's a better direction to go than graphics.
Obviously the best part of programming, as per the title of this blog, is building castles in the air -- constructing projects which seems to take on their own reality. So I'm looking forward to some more sessions where we make this thing interesting, while keeping it accessible to a kid who will be twelve soon.