Weight for weight, CodeWars Kata

Weight for weight

My friend John and I are members of the "Fat to Fit Club (FFC)". John is worried because each month a list with the weights of members is published and each month he is the last on the list which means he is the heaviest.

I am the one who establishes the list so I told him: "Don't worry any more, I will modify the order of the list". It was decided to attribute a "weight" to numbers. The weight of a number will be from now on the sum of its digits.

For example 99 will have "weight" 18, 100 will have "weight" 1 so in the list 100 will come before 99.

Given a string with the weights of FFC members in normal order can you give this string ordered by "weights" of these numbers?

Example:

"56 65 74 100 99 68 86 180 90" ordered by numbers weights becomes: 

"100 180 90 56 65 74 68 86 99"

When two numbers have the same "weight", let us class them as if they were strings (alphabetical ordering) and not numbers:

180 is before 90 since, having the same "weight" (9), it comes before as a string.

All numbers in the list are positive numbers and the list can be empty.

Notes

  • it may happen that the input string have leading, trailing whitespaces and more than a unique whitespace between two consecutive numbers
  • For C: The result is freed.

 

문제 설명이 재미를 위해 이것 저것 붙이다 보니 기네요. 우리는 숫자가 나열된 문자열을 받아 이것을 정해진 가중치로 정렬(Ascending)하여 출력해야 합니다.

룰은 다음과 같습니다.

  • 숫자는 숫자를 이루는 하나하나의 개별 숫자의 합으로 가중치를 정합니다. 예를 들어 5656을 더한 11이 가중치가 됩니다.
  • 가중치가 같으면 일반적인 String처럼 정렬합니다. 18090은 가중치가 1로 모두 동일합니다. String은 알파벳 순서로 정렬하기 때문에 이 둘을 가중치로 정렬하면 180, 90순서로 출력됩니다.

인풋은 다음과 같습니다.

  • 숫자가 나열된 문자열

 

My Solution

입력 문자열을 Stream을 이용해 정렬처리한 후 문자열로 반환했습니다. 정렬에는 가중치를 적용하기 위해서 Custom Comparator를 사용했습니다.

가중치 계산을 위해 문자열을 공백문자열로 Split처리했습니다. (split(""))

솔루션 코드

테스트 코드

package com.codewars;

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.Comparator;

public class WeightForWeight {
    public static String orderWeight(String strng) {
        return Arrays.stream(strng.split(" ")).sorted((String a, String b) -> {
            int asum = Arrays.stream(a.split("")).mapToInt(Integer::parseInt).sum();
            int bsum = Arrays.stream(b.split("")).mapToInt(Integer::parseInt).sum();
            if (asum == bsum)
                return a.compareTo(b);
            else
                return Integer.compare(asum, bsum);
        }).collect(Collectors.joining(" "));
    }
}

 

Best Practice

BP1

첫 번째 BP는 제 솔루션과 유사하지만 String.chars()를 이용했습니다. String.chars()를 이용하면 Split하지 않고 스트림을 바로 생성할 수 있네요. 기억해 두면 좋을 듯 합니다.

class BP {
    public static String orderWeight(String string) {
        String[] split = string.split(" ");
        Arrays.sort(split, new Comparator<String>() {
            public int compare(String a, String b) {
                int aWeight = a.chars().map(c -> Character.getNumericValue(c)).sum();
                int bWeight = b.chars().map(c -> Character.getNumericValue(c)).sum();
                return aWeight - bWeight != 0 ? aWeight - bWeight : a.compareTo(b);
            }
        });
        return String.join(" ", split);
    }
}

 

BP2

두 번째 BP는 ComparatorthenComparing메서드를 활용했습니다. sumDigits(String s)를 미리 생성해두고 BP2::sumDigits로 간결하게 비교한 것도 눈여겨 볼만 합니다. 여러 BP 중 가장 멋있는 코드인 것 같습니다.

class BP2 {

    public static String orderWeight(String strng) {
        return Arrays.stream(strng.split(" "))
                .sorted(Comparator.comparing(BP2::sumDigits).thenComparing(String::compareTo))
                .collect(Collectors.joining(" "));

    }

    private static Integer sumDigits(String s) {
        return s.chars().map(c -> c - 48).sum();
    }
}

 

728x90
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기