Mastodon Development – Page 2 – Josh Hrach

Swift Coding Puzzles #2 – Balanced Brackets

This is part of a series of coding puzzles inspired by the #CodingPuzzle tag/puzzles originally curated and shared by Ali Spittel. This is my approach to solving those puzzles in Swift. If you have any comments or answers you want to share, post them below! I’d love to read them.


Puzzle #2

Given strings of brackets, determine whether each sequence of brackets is balanced.

When would you come across a situation like this? Well, if you ever write a source editor, you might come across something like this. As most programming languages use brackets to denote context, functions, and other divisions, we’ve probably all come across a situation where we forgot to close something off.

For the sake of this exercise, let’s define what brackets mean. In this case, it’ll be three sets of characters: ( ) , [ ] , and { } . The first character we’ll call the “open bracket” and the latter the “close bracket”.

So, what makes a balanced sequence?

  1. A matched pair of brackets.
  2. Any nested brackets must also be matched pairs.

An example of some balanced sequences include: () , [(){}] , {([()])}

An example of some imbalanced sequences include: (() , [([)]] , {([)]}

If any of those become unpaired, then the entire sequence is considered imbalanced. If you’ve ever created a class in Swift and forgot to close a brace when defining functions, you’ll know what that is.

By the above definitions, we can thus determine that in a balanced sequence:

  1. It has an even number of brackets
  2. An open bracket will never meet a close bracket of a different type
  3. A closed bracket will never appear before its corresponding open bracket

That said, here’s how I approached the problem.

First, I defined what each of the brackets were.

let brackets: [Character: Character] = [
    "[":"]",
    "(":")",
    "{":"}"
]
var openBrackets: [Character] { return Array(brackets.keys) as! [Character] }
var closeBrackets: [Character] { return Array(brackets.values) as! [Character] }

Using a dictionary, I’ll be able to easily look up the close bracket for a given open bracket.

Next, let’s look at my function to solve this.

func isBalanced(_ string: String) -> Bool {
    if string.count % 2 != 0 { return false }
    var stack: [Character] = []
    for character in string {
        if closeBrackets.contains(character) {
            if stack.isEmpty {
                return false
            } else {
                let indexOfLastCharacter = stack.endIndex - 1
                let lastCharacterOnStack = stack[indexOfLastCharacter]
                if character == brackets[lastCharacterOnStack] {
                    stack.removeLast()
                } else {
                    return false
                }
            }
        }
        if openBrackets.contains(character) {
            stack.append(character)
        }
    }
    
    return stack.isEmpty
}

First, if the string has an odd number of characters, we automatically fail it. This is in line with point number 1 above.

I then declare a variable to temporarily hold brackets. This stack will be used in the following loop.

Next, we go through each character of the string. Our first check is whether the character is a close bracket or not. If it is, and our stack is empty, it means we’re encountering a close bracket before its open bracket counterpart. We thus return false. If the stack isn’t empty, we check if the last character on the stack is an open counterpart of this close bracket. If it is, we remove the open bracket from the stack. Otherwise, we return false.

If it’s not a close bracket, we’re likely looking at an open bracket. Those automatically get added to the stack.

This loop functions for all characters in the string. Afterwards, our return is whether or not the stack is empty. If it’s not empty, it meant we had more open brackets than closed brackets, and while the earlier catches may not have produced a return, it technically is an unbalanced bracket set.

Here are a few sample calls to this function and their outputs.

isBalanced("()") // True
isBalanced("[]") // True
isBalanced("][") // False
isBalanced("[][") // False
isBalanced("()()") // True
isBalanced("[(){}]") // True
isBalanced("{{[()()][]}}") // True
isBalanced("[]()({)}") // False
isBalanced("(((") // False

I had initially hoped to tackle this with recursion, but I found the above solution to be easier to follow and much easier to manage.

Did you have a different solution? Is there something I could improve with my Swift code? I’d love to hear from you!

Swift Coding Puzzles #1 – Simple Pig Latin

I’ve been following Ali Spittel‘s #CodingPuzzle challenges. While I’ve read most of them, I haven’t actually done them.  But each of them would be a fun little exercise. So, I figured I’d go back and tackle each of them in Swift.

Before I start, a note: There are always multiple ways to tackle coding challenges. This is just my approach to it. If there are better/more optimal ways of doing it, please comment and share your solutions! I’d love to see them. This is as much a way for me to share what I’ve done as it is for me to learn from how others see problems and want to solve them.

That said, here is the first puzzle:

Puzzle #1 – Simple Pig Latin

“Move the first letter of each word to the end of it, then add “ay” to the end of the word. Leave punctuation marks untouched.”

If this was just taking a sentence without punctuation, this would be a lot easier. You could split the array, modify the words, and rebuild the sentence. But keeping punctuation untouched adds a bit of a challenge.

Being me, I also wanted to make sure that this would handle if someone inadvertently misses a space after some punctuation. (No, this likely doesn’t handle apostrophes properly, so contractions will probably not be correct; but I’m no native Pig Latin speaker to know.) So I may have put a little too much thought into this.

First, I wanted to make a function that modifies a word into its proper Pig Latin form.

/// Takes a word and makes it Pig Latinized
func pigLatin(word: String) -> String {
    var newWord = word
    let startIndex = newWord.startIndex
    let firstCharacter = newWord[startIndex]
    newWord.append(firstCharacter)
    newWord.append("ay")
    newWord.remove(at: startIndex)
    return newWord
}

With this function, I can now pass in parts of a sentence as needed. With that done, now I just need to get the words to pass in.

I could have split the array based on space, but that wouldn’t necessarily preserve punctuation. So I instead opted to go through the string character-by-character and parsing words that are found.

func simplePigLatin(_ text: String) -> String {
    let characterSet = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
    var piggyText = ""
    var temporaryWord = ""
    for (index, character) in text.enumerated() {
        let scalar = character.unicodeScalars.first!
        if characterSet.contains(scalar) || index == text.count - 1 {
            if temporaryWord.count > 0 {
                let pigLatinWord = pigLatin(word: temporaryWord)
                piggyText.append(pigLatinWord)
                temporaryWord = ""
            }
            
            // Append any punctuation or white space
            if characterSet.contains(scalar) {
                piggyText.append(character)
            }
        } else {
            // Append letter to temporary word
            temporaryWord.append(character)
        }
    }
    
    return piggyText
}

I go through each character and, if it’s a letter, I add it to a temporary word. If I hit a non-letter (punctuation or whitespace) or the end of the string, I take that temporary word, modify it for authentic Pig Latin, and append it to the return string.

With all of that, here are some sample outputs:

let word = simplePigLatin("I wish I could speak in Pig Latin; I really do!")
print(word) // Iay ishway Iay ouldcay peaksay niay igPay atinLay; Iay eallyray oday!

let contractions = simplePigLatin("I've got day-to-day issues.")
print(contractions) // Iay'evay otgay ayday-otay-ayday ssuesiay.

let badSpacing = simplePigLatin("I forgot,this is not where commas,go")
print(badSpacing) // Iay orgotfay,histay siay otnay hereway ommascay,ogay

So that’s how you can do Pig Latin in Swift. No, it’s not perfect. There are other cases that aren’t dealt with, such as how to handle words starting with vowels or ‘qu’. But I’m no linguist.

Managing Time for Side Projects

I’m quickly coming up on my two year anniversary at my day job. I’ve learned quite a lot in my professional experience as an iOS developer. But one unfortunate side effect of doing something that I love during the day: it’s hard to find the time and motivation needed to work on my app projects, even when the desire is there.

Max’s tweet was originally about trying to work too much. But I felt inspired to address some of the issues as to why I feel I don’t work enough, whether or not that’s true.

The Problem(s)

Here are a few of the issues I’ve found myself facing:

  • Too Many Ideas – My mind seems to come up with new side projects at least once a month. Of course, there’s no way for me to complete (or even start) many of these. But this has been happening for a while. I still have a file in Evernote with about 6 years of app and service ideas. I want to work on one, but I sometimes get distracted with my list and lose focus on what is achievable.
  • Wrong Project Scope – For the ideas that I am able to actually work on, I find myself dreaming up massive plans. ‘Maybe I’ll completely rewrite X!‘ ‘I could do Y like this, but if I do it like this, it’ll be future proof and everything!‘ What was going to be a simple project that I could enjoy working on becomes a large project that might as well take my full time.
  • Too Little Time – I know what you’re going to say. “Isn’t that the whole point of this post?” Well, yes. But it’s worth mentioning. It’s hard to work on side projects when you spend time playing games or watching TV.  If you’ve set aside time for yourself, you are in control of what happens with that time. And that doesn’t always mean those desired projects get a share of it.Nor does that take into account responsibilities you might have if you’re a husband or father and the time you need to spend with your family.

The Solutions(?)

Before I had my current job, I did a lot of my development work on the side. Sometimes I even found some time during the lulls of the day to get a little bit of work done. But now, I have to try other things.

A few things I’ve ultimately realized:

  • I have to make up my mind. Some work I’ve done on my projects lately has stalled because I can’t make up my mind on what to do. In one example, I’m considering using Realm as a data store. I use Realm at work. It’s something I’m fairly comfortable with. But then I think that I could use this time to try working with Core Data again. Or maybe I’ll just stick to using SQLite directly but use a new library. Soon, I’m stuck in this cycle of each direction being one to consider, but I end up doing nothing but considering choices and don’t end up going any one way. So I’ve started telling myself, as my own boss on these projects, that I have to make a choice, stick with it, and move on.
  • I don’t have to be perfect. Similar to the last point, these projects exist for me and me alone. While I am particular about the quality of my own work, I am not going to be pushing these through any kind of code review. So I can let some things slide. If anything, it gives me things I can address with future releases. But ultimately, I don’t need to perfect something before I release it. So long as it works, I can be content.
  • I have to know what I’m doing. I’ve been a fan of Asana for several years. While it was great for my day jobs, I started using it over a year ago for my side projects.  It doesn’t need to be as complicated as my day job (with Epics, Work Requests, and Iteration planning), but I do need to have some idea for what I want my deliverables to be. Setting that for my various projects, including reasonable feature sets for various stages of release, is helping me to make progress.
  • I need a long term plan. I decided earlier this year to go overboard and plan out my 2018 project goals. I’ve got quarterly release goals (mostly Alpha and Beta releases), planned App Store releases, and a general idea of what I would like to accomplish this year. All of it is set up to be achievable but not overwhelming. So no, I’m not launching 6 new apps this year. Yes, I’m hoping to have at least 1 app update and 1 new app on the App Store by December. ((I said it was achievable. I didn’t say it was impressive.))

Overall, I’m not getting as much done with my side app projects as I’d like. But as I am a developer during the day, that takes a lot of my developer energy. And lastly, I have to balance my interest in side projects with my family, which has my ultimate priority. Thankfully, it’s kept me from being a workaholic. ((As much as I love to work.))

In my case, I just have to accept the reality: I can’t do what I once could. But that’s okay. ((I started this blog post shortly after Max’s initial tweet, and that was 4 days ago. Shows you how my time is allocated.))

iOS today view widgets and margins

One of the toughest things I’ve had to deal with while working on an app has been the today view widget. The widget I’ve been working on is very simple: 2 buttons and a label. Yet, there were a couple of issues I kept running into.

  1. When loading the widget, my buttons will appear and layout. With a button tap, the two buttons change size to what is constrained in the Storyboard. This only happens when the widget is loaded and with the first tap. Subsequent taps don’t affect it again.
  2. The widget, as much as I tried, would not appear as it did in the storyboard. Things weren’t centered properly.

The first item I still haven’t solved. The issue that ended up solving the second item is what I thought was affecting the button layout. Essentially, here is what I had: left button is x points from the left edge of the view, is y points from the right button, and has a width equal to the right button. The right button is the same except it has a constraint to the right edge of the view instead of the left. I had hoped that this would lead to a dynamic button size that would change on various devices and widths. Unfortunately, the small issue with the resizing buttons kept bothering me. If someone can figure this out, let me know.

The second issue was actually fairly easy to figure out. If you look at any of your current widgets, you probably notice two different layouts: ones that are full width, and ones that start indented.

I thought that Apple wanted all widgets indented, but there are even some of Apple’s own widgets that are full width. While it wouldn’t solve the first issue I was having (and gave up on), it did impact why the storyboard, set to the width of the device, wasn’t looking like what my widget was showing.

To solve this, make use of the NCWidgetProviding protocol. There is a method called widgetMarginInsetsForProposedMarginInsets  that you can use to either accept the default margin or set it to a custom value.

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
    return UIEdgeInsetsZero;
}

By removing the insets, I suddenly had a widget that not only was centered but also was taking up the space in the view as it was in the Storyboard.

If you want to see what I was working on, check out Countr on the App Store.

Countr, my first app on the App Store

It’s been many months since I last talked about app development. I’m a bit disappointed with myself, personally, and how much I haven’t shared. It’s been a fun experience as I’ve dived into Objective-C, Xcode, and learning how to develop things on my own. Since then, iOS 8 was previewed (and since launched), Swift was introduced as a new programming language, and more APIs and development tool updates have happened across the Apple ecosystem.

Well, I’ll be writing more thoughts about the development process soon. But first, I wanted to talk about the first app I’ve developed through to launch. That is Countr, a simple app to quickly take a count. I had wanted an app to help me take a count when I’m at certain meetings or assemblies. I feel this app does this excellently.

While the app was released in late August, I only just now announced it. Moving to Arizona took up a lot of time. Go figure.

Countr not only helped me learn the development process, but I got a nice overview of the app release process. I’m very grateful for the update to iTunesConnect, which has made it a much more attractive experience when checking on the status of my app.

In upcoming posts, I’ll talk about developing Countr, developing for iOS in general, and some other things that I thought were pretty cool.

I want to thank the few friends that helped beta test Countr before release. I got a lot of good feedback and, while it is a simple app, the others that I’m working on are not as simple. I made sure to use the same process with Countr that I would expect with a larger, complex application. It’s been insightful, and I’m ready to release more apps later this year.

Countr is available for free on the App Store.

My Adventures In App Development (Part 1: The Beginning)

I hate saying that I’m relatively new to app development, but I am. I had originally moved into the Apple ecosystem in 2009 with somewhat of a desire to develop applications. At the time, however, I was spending most of my development time on websites. App development seemed like a much more daunting task.

Over the years, I would occasionally open up Xcode with the intent of creating some kind of basic iPhone app. Each time, though, it seemed like such a different beast than what I was used to. (The MVC model wasn’t a stranger to me, but I didn’t have a lot of experience with it at the time.) I’d add in a few buttons and views, type up some code, but I couldn’t get myself to really dive into it.

One thing I’ve come to really love using since I first got my first iPhone in 2009 is Evernote. I use it to store notes about almost anything, from guitar tab to food recipes. For a while now, I’ve also stored different ideas that come into my head. As I put more and more ideas down in writing, I was able to get a better idea of what I wanted to do.

Two breakthroughs helped me to really push forward in app development, however. The first was making use of video tutorials online, especially on iTunes U, that helped me to really learn and understand Objective-C and iOS app development. Finding an iOS development course is a big plus, as it is just like being in a class where you are taught how to develop for the iPhone and iPad. It definitely beats just reading documentation and following along in a book.

Second was the latest iOS release, iOS 7. As soon as I saw the new look and feel of iOS unveiled at WWDC, as well as reading about the new APIs built into the release, I became excited for development again. In fact, I hadn’t felt this excited about it before.

It was with iOS 7 that my interest was aflame again. Since June, I’ve been pushing forward and working on several ideas. I’ve not been so excited about iPhone app development as I am now. I have a few projects on the burners and, as they get closer to release, I’ll start sharing some information about them, either here or via my business site (which will be updated soon). I’ll also document my travels as I learn more about Objective-C, Xcode, and developing for the iPhone, iPad, and Mac.

[C#] Using Nini .NET Configuration Library

When developing a desktop application, there will be times when you want to store settings for your program. A database is one option, but on Windows, you might just wish to have your settings stored in an INI file. One way to work with an INI file in C# is with the Nini Library. This makes it quite easy to read from and write to an INI file.

Let’s get started.

After installing the library, we’ll need to set our namespace.

using Nini.Config;Code language: CSS (css)

What will our INI file look like? Something like this:

;conf.ini
[Options]
Zipped = 0
Filename = test.txt

For my application, I decided to make a class devoted to the configuration file. So, let’s define that and a few other variables.

public class OurConfig
{
string NL = Environment.NewLine; // New line character
private string configFile = "conf.ini"; // Our INI file

IConfigSource config; // Instance of our config

}Code language: PHP (php)

Now that we have our variables declared, let’s create a couple of useful methods.

public void set_is_zip(int zipped)
{
config.Configs["Options"].Set("Zipped", zipped);
}

public void set_filename(string fname)
{
config.Configs["Options"].Set("Filename", fname);
}Code language: JavaScript (javascript)

These two methods will update the INI file with new settings, should we change them in our program. Of course, if we make these changes, they need to be saved. Thankfully, we can declare something in our constructor (which we will write a little later) that will auto-save our changes as we make them.

config.AutoSave = true;Code language: JavaScript (javascript)

Now, let’s create a pair of methods to return the data. This will be useful in our program when we need to use these settings.

public int return_is_zip()
{
return config.Configs["Options"].Get("Zipped");
}

public string return_filename()
{
return config.Configs["Options"].Get("Filename");
}Code language: PHP (php)

With these methods, we now have a basic class for handling a configuration file. All that is left is our constructor.

But before we get to the constructor, there is something else I created. What if our INI file doesn’t exist? I decided that I would make a function to create a default INI file, should the old one not exist anymore. This is also useful if we want to distribute our program without an INI file.

private void fill_new_ini()
{
// Put default values into the INI file
// Essentially, we're writing a blank file, so this is fairly simple
string toWrite = ";conf.ini" + NL
+ "[Options]" + NL
+ "Zipped = 0" + NL
+ "Filename = test.txt" + NL;

System.IO.File.WriteAllText(@"conf.ini", toWrite);
}Code language: JavaScript (javascript)

We can do a check when we initialize our class that will check to see whether or not this file exists. If not, we’ll create it so we can work with it.

That makes this our constructor:

public OurConfig()
{
// Initialize the INI file if it doesn't exist
try
{
configFile = new IniConfigSource("conf.ini");
}
catch (Exception ex)
{
// Write default values into it
fill_new_ini();
configFile = new IniConfigSource("conf.ini");
}

configFile.AutoSave = true; // Auto save config file as we make changes

}Code language: PHP (php)

Our whole class thus looks like this:

using Nini.Config;

public class OurConfig
{
string NL = Environment.NewLine; // New line character
private string configFile = "conf.ini"; // Our INI file

IConfigSource config; // Instance of our config

public OurConfig()
{
// Initialize the INI file if it doesn't exist
try
{
configFile = new IniConfigSource("conf.ini");
}
catch (Exception ex)
{
// Write default values into it
fill_new_ini();
configFile = new IniConfigSource("conf.ini");
}
configFile.AutoSave = true; // Auto save config file as we make changes
}

private void fill_new_ini()
{
// Put default values into the INI file
// Essentially, we're writing a blank file, so this is fairly simple
string toWrite = ";conf.ini" + NL
+ "[Options]" + NL
+ "Zipped = 0" + CL
+ "Filename = test.txt" + CL;
System.IO.File.WriteAllText(@"conf.ini", toWrite);

}

public void set_is_zip(int zipped)
{
config.Configs["Options"].Set("Zipped", zipped);
}

public void set_filename(string fname)
{
config.Configs["Options"].Set("Filename", fname);
}

public int return_is_zip()
{
return config.Configs["Options"].Get("Zipped");
}

public string return_filename()
{
return config.Configs["Options"].Get("Filename");
}

} // End OurConfigCode language: PHP (php)

That’s how simple it can be to work with your own INI files in C#.

Did you find this useful? Let me know in the comments!

Working with DataTable in C#

One thing I’ve had to do lately is learn some C#. I will admit that it isn’t the language I would prefer to work with during the week, but it does help me become more versatile when it comes to application development.

Working with C#, I had to take data and enter it into a data grid. Being that I still consider myself a C# newbie, I figured this was something I might as well learn to use.

In the end, creating a data table in C# isn’t that difficult. In this example, I’ll be taking data from a Microsoft Access database and entering it into a DataTable object.

First, let’s define our DataTable and its columns.

[crayon lang=”C#”]

DataTable table = new DataTable();

table.Columns.Add(“Name”, typeof(string));
table.Columns.Add(“Age”, typeof(int));
table.Columns.Add(“Weight”, typeof(int));

[/crayon]

Now, while it isn’t necessary, I like having temporary variables to hold data from a database before entering it into our table. For what we have, that would be:

[crayon lang=”C#”]

string theName;
int theAge;
int theWeight;

[/crayon]

All that is left to get is the data itself. Assuming we’re getting it from some kind of database, we can get the information in a while loop and add all of the data into the table.

[crayon lang=”C#”]

OleDbCommand cmd = new OleDbCommand(“Select FullName, PersonAge, PersonWeight FROM PersonalInfo”, con); // Our Query
OleDbDataReader reader = cmd.ExecuteReader(); // Execute Query
while (reader.Read()) // If we can read rows…
{
// Show records in text fields
theName = reader.GetString(0);
theAge = reader.GetInt32(1);
theWeight = reader.GetInt32(2);

table.Rows.Add(theName, theAge, theWeight);
}

[/crayon]

Now we have our data in the DataTable. All that is left is to output it. For this, I have a DataGridView object in my form called myDataGrid.

[crayon lang=”C#”]

myDataGrid.DataSource = table; // Put DataTable data into our DataGrid
myDataGrid.AutoResizeColumns(); // Automatically resize columns to show all data

[/crayon]

And that’s all there is to using a DataTable in C#.

Have you worked with DataTables? Submit your experiences and comments below!