ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Bash Script: Advanced String Permutation Generator

Bash

Goal -- WPM

Ready
Exercise Algorithm Area
1#!/bin/bash
2
3# Function to generate permutations recursively
4# Args: current_permutation, remaining_chars, used_indices_map
5permute_recursive() {
6local current_permutation="$1"
7local remaining_chars="$2"
8local used_indices_map="$3"
9local original_string="$4"
10local result_array_ref="$5"
11
12# Base case: if no characters are remaining, we have a complete permutation
13if [[ -z "$remaining_chars" ]]; then
14# Add the permutation to the result array
15eval "$result_array_ref+=('$current_permutation')"
16return
17fi
18
19# Iterate through each character in the remaining characters
20local i
21for ((i=0; i<${#remaining_chars}; i++)); do
22local char_to_add="${remaining_chars:$i:1}"
23local next_remaining_chars="${remaining_chars:0:$i}${remaining_chars:$((i+1))}"
24
25# Check if this character has already been used at this level of recursion
26# This is crucial for handling duplicate characters efficiently
27local already_used_at_level=0
28local j
29for ((j=0; j<i; j++)); do
30if [[ "${remaining_chars:$j:1}" == "$char_to_add" ]]; then
31already_used_at_level=1
32break
33fi
34done
35
36if [[ $already_used_at_level -eq 0 ]]; then
37# Recursively call permute_recursive with the updated permutation and remaining characters
38permute_recursive "$current_permutation$char_to_add" "$next_remaining_chars" "$used_indices_map" "$original_string" "$result_array_ref"
39fi
40done
41}
42
43# Helper function to sort a string alphabetically
44sort_string() {
45local str="$1"
46echo "$str" | grep -o . | sort | tr -d '\n'
47}
48
49# Main function to initiate permutation generation
50# Args: input_string
51main() {
52local input_string="$1"
53local permutations=()
54
55# Handle empty string edge case
56if [[ -z "$input_string" ]]; then
57echo ""
58return
59fi
60
61# Sort the input string to handle duplicates easily in the recursive step
62local sorted_input="$(sort_string "$input_string")"
63
64# Call the recursive permutation function
65permute_recursive "" "$sorted_input" "" "$sorted_input" "permutations[@]"
66
67# Remove duplicates from the generated permutations (though the logic should prevent them)
68# and print each unique permutation
69local unique_permutations=$(printf "%s\n" "${permutations[@]}" | sort -u)
70echo "$unique_permutations"
71}
72
73# Example usage:
74# main "abc"
75# main "aab"
76# main ""
77# main "abcd"
Algorithm description viewbox

Bash Script: Advanced String Permutation Generator

Algorithm description:

This Bash script generates all unique permutations of a given input string using a recursive backtracking algorithm. It efficiently handles strings with duplicate characters by sorting the input and skipping redundant recursive calls. This is useful in scenarios like generating all possible orderings for tasks, password cracking simulations, or combinatorial problem-solving where exploring all arrangements is necessary.

Algorithm explanation:

The script employs a recursive backtracking approach to generate permutations. The `permute_recursive` function takes the current partial permutation, the remaining characters to be used, and a map of used indices. The base case is when `remaining_chars` is empty, signifying a complete permutation. In the recursive step, it iterates through each character in `remaining_chars`. To handle duplicates, it checks if a character has already been considered at the current recursion level. If not, it appends the character to `current_permutation`, removes it from `remaining_chars`, and makes a recursive call. The `sort_string` helper ensures that identical characters are adjacent, simplifying the duplicate check. The time complexity is roughly O(N! * N) due to generating N! permutations, each taking O(N) to construct and process. Space complexity is O(N!) to store the permutations and O(N) for the recursion depth. Edge cases like empty strings are handled. The invariant is that `current_permutation` always represents a valid prefix of a permutation, and `remaining_chars` contains the characters yet to be placed.

Pseudocode:

function permute_recursive(current_permutation, remaining_chars):
  if remaining_chars is empty:
    add current_permutation to results
    return

  for each character `char` at index `i` in remaining_chars:
    if `char` has not been used at this level (check against previous chars in remaining_chars):
      next_remaining_chars = remaining_chars without `char` at index `i`
      permute_recursive(current_permutation + `char`, next_remaining_chars)

function main(input_string):
  if input_string is empty:
    return empty list

  sorted_input = sort(input_string) alphabetically
  call permute_recursive("", sorted_input)
  return unique elements from results