HiveBrain v1.2.0
Get Started
← Back to all entries
debugjavaMinor

Broken keyboard challenge

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
keyboardbrokenchallenge

Problem

Inspired by Reddit r/dailyprogrammer


Help! My keyboard is broken, only a few keys work any more. If I tell you what keys work, can you tell me what words I can write?

The program works fine, not really any additions I wish to make to it. Was just wanting some general feedback on the layout, structure and efficiency.

Note: The dictionary used can be found in the given link.

```
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

/**
* Created on 7/1/2016.
*
* Inspired by r/dailyprogrammer
* https://www.reddit.com/r/dailyprogrammer/comments/3pcb3i/20151019_challenge_237_easy_broken_keyboard/
*/

public class BrokenKeyboard {

private static List wordDict;
private static final String dictPath = "Dictionaries/EnglishWords.txt";

/**
* The main acquires input from the user then
* applies it to the other below methods.
* @param args Unused.
*/

public static void main(String args[]) {
BrokenKeyboard.setDict(dictPath); // Stores dictionary in list.
System.out.println("Processing...");
System.out.println(String.join(", ", findMatches("bikn", wordDict)));
}

/**
* Used to load a given text file into memory.
* @param filePath Used to specify the path of the file that needs to be loaded into memory.
*/
private static void setDict(String filePath){
try {
wordDict = Files.readAllLines(new File(filePath).toPath());
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* Used to compare a given key to the text file loaded into memory.
* @param key The inputted set of characters compared to the given dictionary.
* @param dict The list of words that will be used to compare to the key.
* @return The list of matches made when comparing the key with the given dictionary.
*/
private static List findMatches(String key, List di

Solution

setDict() is a bit of a misnomer; loadDict() would be more accurate. Since the loaded dictionary becomes part of the global state, it would be more appropriate to make it an instance variable than a static variable. If loading fails, you shouldn't just print a stack trace and attempt to continue execution — that defeats the purpose of exceptions. In general, if you don't have a good way to handle an exception, just propagate it (by declaring throws IOException).

Your technique for checking whether a word consists solely of a limited set of characters is to do repeated string replacement. That would cause a lot of temporary objects to be allocated and discarded. A more appropriate tool to use would be a regular expression match (using Pattern.compile("^[bikn]*$"), for example).

Since this is a filtering exercise, it would be more eloquently written using Stream.filter(Predicate) instead of List.

Although String args[] is syntactically valid, String[] args is considered more idiomatic in Java, since String[] is considered the type.

Suggested solution

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BrokenKeyboard {
    public static Predicate typableUsing(String availableKeys) {
        // CAVEAT: availableKeys is assumed not to contain regex metacharacters
        // such as ^ [ ] - \
        return Pattern.compile("^[" + availableKeys + "]*$").asPredicate();
    }

    public static Stream dictionary(File f) throws IOException {
        return Files.lines(f.toPath());
    }

    public static void main(String[] args) throws IOException {
        System.out.println(
            BrokenKeyboard.dictionary(new File(args[1]))
                          .filter(BrokenKeyboard.typableUsing(args[0]))
                          .collect(Collectors.joining(", "))
        );
    }
}


It is possible to resolve the caveat using Pattern.quote(). I'll leave it as an exercise to the reader. =)

Code Snippets

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BrokenKeyboard {
    public static Predicate<String> typableUsing(String availableKeys) {
        // CAVEAT: availableKeys is assumed not to contain regex metacharacters
        // such as ^ [ ] - \
        return Pattern.compile("^[" + availableKeys + "]*$").asPredicate();
    }

    public static Stream<String> dictionary(File f) throws IOException {
        return Files.lines(f.toPath());
    }

    public static void main(String[] args) throws IOException {
        System.out.println(
            BrokenKeyboard.dictionary(new File(args[1]))
                          .filter(BrokenKeyboard.typableUsing(args[0]))
                          .collect(Collectors.joining(", "))
        );
    }
}

Context

StackExchange Code Review Q#133875, answer score: 3

Revisions (0)

No revisions yet.