Post

Java 예제: 로또 (중복없이 배열에서 값 추출, 배열 원소 스왑) + HashSet 이용

Java 예제: 로또 (중복없이 배열에서 값 추출, 배열 원소 스왑) + HashSet 이용

HashSet 이용 (2020년 4월 24일 추가)

Set 자료형은 중복을 허용하지 않는다는 특성을 이용한 코드입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.util.HashSet;
import java.util.Set;

public class SetTest {

  public static void main(String[] args) {
    Set<Integer> lotto = new HashSet<>();

    while(lotto.size() < 6) {
      lotto.add((int)(Math.random() * 45 + 1));
    }

    System.out.println(lotto);

    // Optional: Set to array
    Integer[] lottoArr = new Integer[6];
    lotto.toArray(lottoArr);
    bubbleSort(lottoArr);

    for(int i : lottoArr) {
      System.out.print(i + "\t");
    }

  }

  private static void bubbleSort(Integer[] array) {
    // 버블정렬
    boolean isContinue = false;
    
    int tempNum;
    for (int i = 0; i < (array.length - 1); i++) {            
      for (int j = 0; j < (array.length - i - 1); j++) {
        if (array[j] > array[j + 1]) {
          tempNum = array[j];
          array[j] = array[j + 1];
          array[j + 1] = tempNum;
          isContinue = true;
        }
      }
      if (!isContinue) {
        break;
      }
    }
  }

}

👉 이전 작성 내용보기 ## 이전 작성 내용 랜덤값을 뽑는 게 어려운 건 아니지만 중복없이 랜덤을 뽑는건 상당히 까다로운 작업입니다. 스트레이트로 접근하려고 하면 매우 지저분한 코드가 나올 수 있습니다. 프로그래밍 알고리즘 중에 **카드뽑기(shuffle)** 기법이라는 게 있는데요, 아래와 같은 순서로 진행됩니다. 1. 배열 내에서 임의의 두 값을 선택한 뒤 스왑(swap)한다. 2. 충분한 수 만큼 반복한다. 3. 충분한 수 만큼 반복했다면 배열 내 원소들은 임의의 순서대로 섞여있을 것이며 여기서 원하는 갯수만큼 앞에서든 뒤에서든 추출한다. 카드뽑기 알고리즘을 사용하려면 먼저 스왑에 대해 알아볼 필요가 있습니다. **스왑(swap)** 기법은 배열 등에서 앞과 뒤를 교환하는 알고리즘으로, 배열의 정렬 등에서 사용하며 정보처리기사에서도 단골로 출제되는 문제입니다. 아래는 스왑 예제입니다. ```java public class ArraySwap { public static void main(String[] args) { char[] A = new char[2]; char temp; A[0] = 'A'; A[1] = 'B'; System.out.print(""+A[0]+A[1]); temp = A[0]; A[0] = A[1]; A[1] = temp; System.out.println(""+A[0]+A[1]+": Dancing Queen"); System.out.println("\nYou can dance\r\n" + "You can jive\r\n" + "Having the time of your life\r\n" + "Ooh, see that girl\r\n" + "Watch that scene\r\n" + "Dig in the dancing queen"); } } ``` **_위의 코드에 나오는 가수의 이름은?_**   카드뽑기를 할건데 주제가 로또이므로 숫자 6개를 추출합니다. 반복할 횟수는 시스템의 성능과 알고리즘 시간 등을 고려하여 정하는데 천단위 경우일 경우에는 생각처럼 잘 안섞여서 만단위 이상으로 충분히 진행하는 것이 좋겠습니다. ```java import blog.gui.PrintArray; public class Lotto { static final int LOTTO_NUM = 45; public static void main(String[] args) { int[] lotto = new int[LOTTO_NUM]; int x, y; int temp; // 1~45 일괄 채워넣기 for (int i=0; i < lotto.length; i++) { lotto[i] = i + 1; // System.out.println(lotto[i]); } // 섞기 for(int i = 1; i <= 100000; i++) { x = (int)(Math.random() * LOTTO_NUM); y = (int)(Math.random() * LOTTO_NUM); temp = lotto[x]; lotto[x] = lotto[y]; lotto[y] = temp; } // 새 배열에 옮김 int[] chosenLotto = new int[6]; for(int i = 0; i < 6; i++ ) { chosenLotto[i] = lotto[i]; } // (추가) 버블정렬 int tempNum; for (int i=0; i < (chosenLotto.length); i++) { for (int j=0; j < (chosenLotto.length - 1 ); j++) { if (chosenLotto[j] > chosenLotto[j+1]) { tempNum = chosenLotto[j]; chosenLotto[j] = chosenLotto[j+1]; chosenLotto[j+1] = tempNum; } } } // 표시 new PrintArray("로또 번호 뽑기", chosenLotto); } } ``` `new PrintArray()`는 [Java Swing 예제: 다차원 배열 표시하기 (기초 설정 방법, for문으로 swing 요소 반복 등)](/posts/java-swing-예제-다차원-배열-표시하기-기초-설정-방법-for문으) 에 있습니다.   자바 8 이상에서 사용할 수 있는 **Collections**를 사용한 고급 기법에 대해 알아보겠습니다. `Collections.shuffle(List<?> list);` 를 사용하면 카드뽑기를 훨씬 간편하게 할 수 있습니다. ```java import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import blog.gui.PrintArray; public class LottoShuffle { static final int LOTTO_NUM = 45; public static void main(String[] args) { int[] lotto = new int[LOTTO_NUM]; // 1~45 일괄 채워넣기 for (int i=0; i < lotto.length; i++) { lotto[i] = i + 1; } List list = Arrays.stream( lotto ).boxed().collect( Collectors.toList() ); Collections.shuffle(list); // 섞기 List selection = list.subList(0, 6); // 6개 추출 Collections.sort(selection); // 추출한 6개 정렬 // selection.forEach(System.out::println); new PrintArray("로또 번호 뽑기", selection); } } ``` 참고로 `Collections`의 `shuffle`과 `sort`는 리턴형이 `void`이며, 배열이 아니라 리스트 등의 `Collection`자료형에서 사용 가능한 옵션이므로 배열을 리스트로 바꿔줘야 합니다. 20라인의 `Arrays.stream`이 그 역할을 합니다. `int[]` 형 배열은 스트림으로 변환하는 것이 Wrapper-object 관련 문제를 방지하는 데 도움이 됩니다. ![](/assets/img/wp-content/uploads/2019/01/collection.png) </detail>
This post is licensed under CC BY 4.0 by the author.