Generate All Permutations of a String in Java

Given any string, how many different permutations of that character set can be made? To answer that question, this Java program uses a recursive function to generate all permutations of a string passed as a command line argument. Most permutation generators that I have come across will only output permutations of the same length as the input set, e.g. enter 3 characters and the output will show permutations containing all 3 characters. This program, however, will generate all permutations of the input set from length 1 through n, where n is the total number of characters in the string. For example, if “abc” is entered, the program generates all permutations of length 1 to 3 characters: a, b, c, ab, ac, ba, bc, ca, cb, abc, acb, bac, bca, cab, cba.

Example Permutations of Varying Length for String "abc"
Example Permutations of Varying Length for String “abc”

Why is this useful? It probably isn’t. I wrote the code to see how the number of permutations grew with each additional character. I feel like this is also a standard introduction to Computer Science question so perhaps this will help someone do their homework assignment. From a practical standpoint, I suppose it could be used to help your Scrabble game. If you enter all of the letter tiles from your rack, this will generate all of the possible letter permutations. The code could be modified to validate those permutations against a Scrabble dictionary though it would be awfully suspicious if someone was typing into a computer/device throughout a game.

Usage

The following illustrates the code being compiled and executed using the sample set “abc”.

java Permutation [string]

[string] represents the set of characters to generate all permutations; multiple strings may be passed when separated by a space.
Java Program to Generate All Permutations of a String
Java Program to Generate All Permutations of a String

Source Code

import java.util.ArrayList;
public class Permutation {
  private ArrayList<String> permutations = null;
  private String characters = null;
  public static void main(String[] args) {
    Permutation p = null;
    ArrayList arrlist = null;
    for(String s: args) {
      p = new Permutation(s);
      arrlist = p.getPermutations();
      System.out.println("Generating all permutations of string: "+p.getCharacters());
      for(int i = 0; i < arrlist.size(); i++) {
        System.out.println(arrlist.get(i));
      }
      System.out.println("");
    }
  }
  public Permutation(String characters) {
    if((characters == null) || ("").equals(characters.trim())) {
      characters = "";
    }
    this.characters = characters;
  }
  public String getCharacters() {
    return characters;
  }
  public ArrayList getPermutations() {
    this.permutations = new ArrayList<String>();
    for(int j = 1; j <= getCharacters().length(); j++) {
      permute("",getCharacters(),j);
    }
    return this.permutations;
  }
  protected void permute(String prefix,String s,int length) {
    String word = null;
    for(int i = 0; i < s.length(); i++) {
      word = prefix+s.charAt(i);
      if(word.length() == length) {
        permutations.add(word);
      } else {
        if(i == 0) {
          permute(word,s.substring(i+1,s.length()),length);
        } else if(i == (s.length()-1)) {
          permute(word,s.substring(0,s.length()-1),length);
        } else {
          permute(word,(s.substring(0,i)+s.substring(i+1,s.length())),length);
        }
      }
    }
    return;
  }
}

Java Keypress Generator

The following is a keypress generator using the Robot class in Java. If you provide a string to the constructor and call the simulate() method, each of the characters in the string is generated as a keypress event. In other words, the program simulates the pressing of a key on physical keyboard. This may be used to redirect input to another window.

Usage

java Typer [options] [string] [string] [...]

Options
--delay Sets the processing interval between strings in milliseconds [default: 0 (0 milliseconds)]

[string] represents the set of characters used to generate keypress events; multiple strings may be passed when separated by a space.

Example

The following illustrates the code being compiled and executed using the sample input “test1”, “test2”, “test3” and “test4”. Each keypress event is delayed by 2 seconds (2000 milliseconds). The program is executed and I immediately (manually) move the window focus to the Notepad window. As the program executes, the generated keypress events are received in Notepad because that is the window with active focus.

Executing the Java Keypress Generator
Executing the Keypress Generator

Source Code

import java.awt.Robot;
import java.awt.event.KeyEvent;
public class Typer {
  private Robot robot = null;
  private String characters = null;
  private int iDelay = 0;
  public static void main(String[] args) {
    Typer typerBot = null;
    int iDelay = 0;
    boolean bDelayArg = false;
    for(String s: args) {
      if(bDelayArg) {
        bDelayArg = false;
        try {
          iDelay = Integer.parseInt(s);
          if(iDelay < 0) {
            throw new NumberFormatException("Negative Integer");
          }
        } catch (NumberFormatException e) {
          System.out.println("Error: Delay must be a positive integer in milliseconds.");
          System.exit(1);
        }
      }
      if(s.equalsIgnoreCase("--delay")) {
        bDelayArg = true;
      }
    }
    bDelayArg = false;
    for(String s: args) {
      if(s.equalsIgnoreCase("--delay")) {
        bDelayArg = true;
      } else {
        if(!bDelayArg) {
          System.out.println("Initiating simulation for string: "+s);
          typerBot = new Typer(s, iDelay);
          typerBot.delay();
          typerBot.simulate();
          System.out.println("");
        } else {
          bDelayArg = false;
        }
      }
    }
 
    return;
  }
  public Typer(String characters) {
    if((characters == null) || ("").equals(characters.trim())) {
      characters = "";
    }
    this.characters = characters;
    try {
      robot = new Robot();
    } catch(Exception e) {
    }
    return;
  }
  public Typer(String characters, int iDelay) {
    if((characters == null) || ("").equals(characters.trim())) {
      characters = "";
    }
    this.characters = characters;
    this.iDelay = iDelay;
    try {
      robot = new Robot();
    } catch(Exception e) {
    }
    return;
  }
  public String getCharacters() {
    return characters;
  }
  protected boolean delay() {
    if(this.robot != null) {
      robot.delay(this.iDelay);
      return true;
    }
    return false;
  }
  protected boolean delay(int iDelay) {
    if(this.robot != null) {
      robot.delay(iDelay);
      return true;
    }
    return false;
  }
  private int getKeyCode(char c) {
    int iKeyCode = 0;
    try {
      iKeyCode = KeyEvent.getExtendedKeyCodeForChar(c);
    } catch(Exception e) {
    }
  
    return iKeyCode;
  }
  public boolean simulate() {
    int iKeyCode = 0;
    if(robot == null) {
      return false;
    }
    for(int i = 0; i < this.getCharacters().length(); i++) {
      iKeyCode = getKeyCode(this.getCharacters().charAt(i));
      robot.keyPress(iKeyCode);
      robot.keyRelease(iKeyCode);
    }
    robot.keyPress(KeyEvent.VK_ENTER);
    robot.keyRelease(KeyEvent.VK_ENTER);
    return true;
  }
}

Enable Browser Caching Directives in Amazon Lightsail Apache Server

By default in an Amazon Lightsail LAMP image, the Apache HTTP server is not configured with browser caching directives enabled. Specifically, the mod_expires Apache module is not loaded. If you’re not familiar with browser caching directives, this module controls the Expires HTTP header and the max-age directive of the Cache-Control HTTP header in server responses. These inform the browser how long to cache responses. If a resource is mostly static and doesn’t change very often, then the directive should establish a longer caching period vs. a resource that may be changing hourly. This directive reduces bandwidth consumption and server load while improving user experience by loading screens faster since the browser isn’t repeatedly requesting the same file.

Log into the Amazon Lightsail server and edit the httpd.conf file. In this example, the httpd.conf file is located in /opt/bitnami/apache/conf/ so you may need to adjust the path depending on your image.

sudo vim /opt/bitnami/apache/conf/httpd.conf

Find the mod_expires.so entry in the file, remove the comment (#), and save the file. The server does not need to be restarted.

LoadModule expires_module modules/mod_expires.so

In the .htaccess file for your site, you can add various Expires directives for relevant file types. This example provides a small sample of common file types and can be expanded to meet your particular needs. Please adjust the expiry times as appropriate for your site. A more detailed walkthrough of .htaccess files can be found at Hardening WordPress Security Using .htaccess.

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 month"
  ExpiresByType text/html "access plus 0 seconds"
  ExpiresByType image/gif "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType image/jpg "access plus 1 year"
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType text/css "access plus 1 month"
  <IfModule mod_headers.c>
    Header append Cache-Control "public"
  </IfModule>
</IfModule>

As a demonstration of the directive in action, PNG image files are set to a one year cache from the time the file is accessed. In the following image, a file accessed on June 24, 2021 (date) expires in the cache one year later on June 24, 2022 (expires). This information can be viewed in most browsers using the Inspect feature and activating the Network Monitor.

Response Headers: cache-control
Response Headers: cache-control

The browser also shows that the file was transferred from the cache and no additional bandwidth was consumed for that resource.

File Cache Transfer Status
File Cache Transfer Status