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

Reverse each group of k elements in a list

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

Problem

Challenge

Given a list of numbers and a positive integer k, reverse the elements of the list, k items at a time.
Specifications

  • The first argument is a path to a file.



  • The file contains multiple lines.



  • Each line is a test case represented by a comma separated list of numbers and the number k, separated by a semicolon.



  • Print the comma separated list of numbers after reversing.



  • If the number of elements is not a multiple of k, then the remaining elements should be unaltered.



Sample Input

1,2,3,4,5;2

1,2,3,4,5;3

Sample Output

2,1,4,3,5

3,2,1,4,5

Source

My Solution

```
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Solution {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("No file path provided.");
System.exit(1);
}

if (args.length >= 2) {
System.out.println("Excessive arguments only the first will be considered.");
}

try (Scanner file = new Scanner(new File(args[0]))) {
while (file.hasNextLine()) {
System.out.println(reversed(file.nextLine()));
}
} catch (FileNotFoundException fnfe) {
System.err.println("Could not find file.");
}
}

private static String reversed(String line) {
String[] helper = line.split(";");
int k = Integer.parseInt(helper[1]);
if (k == 0) {
return helper[0];
}
return reversedByK(helper[0].split(","), k);
}

private static String reversedByK(String[] nums, int k) {
StringBuilder result = new StringBuilder();
for (int i = k - 1; i < nums.length; i += k) {
for (int j = i; i - j <= k - 1; j--) {
result.append(',').append(nums[j]);
}
}

for (int i = nums.length - nums.length % k; i < nums.length; i++) {
result.append(',').append(nums[i]

Solution

The core of your solution doesn't suit my taste:

private static String reversedByK(String[] nums, int k) {
    StringBuilder result = new StringBuilder();
    for (int i = k - 1; i < nums.length; i += k) {
        for (int j = i; i - j <= k - 1; j--) {
            result.append(',').append(nums[j]);
        }
    }

    for (int i = nums.length - nums.length % k; i < nums.length; i++) {
        result.append(',').append(nums[i]);
    }
    return result.substring(1);
}


My main gripe is that it works at two different levels: it accepts an array as input, but returns a string. It's a mild violation of the Single Responsibility Principle. One consequence is that it uses the assumption that a comma should be used as a delimiter. It would be more elegant if whichever function performed .split(",") were also responsible for doing String.join(",", …).

Also consider taking advantage of the Scanner more to help you with parsing the input.

private static final Pattern DELIM = Pattern.compile(";|\n|\r");

public static void main(String[] args) {
    …
    try (Scanner file = new Scanner(new File(args[0])).useDelimiter(DELIM)) {
        while (file.hasNextLine()) {
            System.out.println(reversedByK(file.next(), file.nextInt()));
            file.nextLine();
        }
    } catch (FileNotFoundException fnfe) {
        System.err.println("Could not find file.");
    }
}

private static String reversedByK(String list, int k) {
    String[] array = list.split(",");
    reversedByK(array, k);
    return String.join(",", array);
}

private static void reversedByK(String[] array, int k) {
    for (int i = 0; i + k <= array.length; i += k) {
        for (int a = i, b = i + (k - 1); a < b; a++, b--) {
            String swap = array[a];
            array[a] = array[b];
            array[b] = swap;
        }
    }
}


One bonus benefit of this swap-in-place solution is that there is no need for a second loop in reversedByK() to handle the remaining elements.

Code Snippets

private static String reversedByK(String[] nums, int k) {
    StringBuilder result = new StringBuilder();
    for (int i = k - 1; i < nums.length; i += k) {
        for (int j = i; i - j <= k - 1; j--) {
            result.append(',').append(nums[j]);
        }
    }

    for (int i = nums.length - nums.length % k; i < nums.length; i++) {
        result.append(',').append(nums[i]);
    }
    return result.substring(1);
}
private static final Pattern DELIM = Pattern.compile(";|\n|\r");

public static void main(String[] args) {
    …
    try (Scanner file = new Scanner(new File(args[0])).useDelimiter(DELIM)) {
        while (file.hasNextLine()) {
            System.out.println(reversedByK(file.next(), file.nextInt()));
            file.nextLine();
        }
    } catch (FileNotFoundException fnfe) {
        System.err.println("Could not find file.");
    }
}

private static String reversedByK(String list, int k) {
    String[] array = list.split(",");
    reversedByK(array, k);
    return String.join(",", array);
}

private static void reversedByK(String[] array, int k) {
    for (int i = 0; i + k <= array.length; i += k) {
        for (int a = i, b = i + (k - 1); a < b; a++, b--) {
            String swap = array[a];
            array[a] = array[b];
            array[b] = swap;
        }
    }
}

Context

StackExchange Code Review Q#140528, answer score: 4

Revisions (0)

No revisions yet.