반응형

에러 전문

Oct 28, 2022 8:15:45 PM org.junit.platform.launcher.core.EngineDiscoveryOrchestrator lambda$logTestDescriptorExclusionReasons$7
INFO: 0 containers and 10 tests were Method or class mismatch

 

 

에러 상황

- 테스트 코드 중 특정 클래스만 실행할 때 발생했다.

 

 

에러 이유

작성된 테스트 코드 중 특정 클래스만 실행했다는 경고문이다.

실제로 실행시킨 테스트 코드는 잘 실행되었으며, 전체 테스트 코드 실행 시 해당 경고문이 발생하지 않았다.

테스트에는 아무 문제가 없었다.

 

또한, 빌드할 때 JUnit으로 테스트가 진행 되어야 하는데 Gradle로 되어서 발생하는 것이라고 한다.

Gradle 에서 Intellij IDEA로 변경하면 해당 경고문이 발생하지 않는다.

 

mac기준, 아래와 같이 IntelliJ 설정을 변경하면 된다.

 

 

 

 

참고 링크 : https://stackoverflow.com/questions/68465659/what-causes-a-junit-warning-org-junit-platform-launcher-core-enginediscoveryorch

 

What causes a junit warning org.junit.platform.launcher.core.EngineDiscoveryOrchestrator lambda$logTestDescriptorExclusionReason

I have a gradle-based java testing framework. After updating junit to 5.7.2 this warning started appearing for every test: Jul 21, 2021 10:23:45 AM org.junit.platform.launcher.core.

stackoverflow.com

https://www.inflearn.com/questions/157200

 

질문하나만 드려도될까요.. - 인프런 | 질문 & 답변

테스트는 성공으로 뜨는데  빨간색으로 이런 글씨가 있어서 왜 이런게 뜨는지 여쭤봐도 될까요..?  org.junit.platform.launcher.core.EngineDiscoveryOrchestrator lambda$logTestDescriptorEx...

www.inflearn.com

 

반응형
반응형

Java IDE인 IntelliJ에서 JDK 버전을 바꾸는 방법을 정리해보고자 한다.

* m1 프로세서(arm)을 사용하는 macOS 버전입니다.

 

대략 아래와 같은 순서로 진행된다.

1. IntelliJ에서 JDK 버전 바꾸기

2. 원하는 버전이 없다면 다운로드

3. 터미널에서 환경변수 설정하기.

 

가끔 한 프로젝트는 8 버전을, 한 프로젝트는 11 버전을 사용해야하는 분들이 있는데,

위의 1번과 3번을 계속 왔다리갔다리 설정하면 된다.

(IntelliJ 설정 변경 + 환경변수 변경)

 

 

 


1. IntelliJ JDK 버전 바꾸기

IntelliJ 좌측 상단 메뉴바 - File - Project Structure - SDK

이 곳에서 원하는 버전을 설정하면 되는데, 없다면 아래 2번으로 가서 설치 후 설정을 변경해야 한다.

 

 

* Language level이란? (참고 링크: https://atoz-develop.tistory.com/entry/JAVA-IntelliJ-IDEA-Project-language-level-%EC%84%A4%EC%A0%95%EC%9D%98-%EC%9D%98%EB%AF%B8)

Project language level은 IntelliJ의 editor(편집기)와 java compiler가 사용할 language level을 설정한다. 예를 들어, JDK 1.7을 사용하고 있지만 java 코드가 JDK 1.6과 호환되도록 하려면 language level 실제 JDK 지원(JDK 1.7의 경우 7.0)보다 낮은 6.0으로 설정하면 된다.

 

Java 컴파일러 명령인 javac의 옵션을 보면 -source 및 -target 옵션을 통해 Java의 대체 버전을 기준으로 컴파일할 수 있음을 알 수 있다. 이를 통해 Project language level은 IntelliJ에게 특정 Java 언어 버전에서 제공된 Java SDK를 사용하도록 지시한다.
그래서 Java 7이 설치되어 있어도 language level을 6.0으로 설정할 수 있고, IntelliJ는 Java 7 대신 Java 6을 기준으로 코드를 확인하고, suggestion을 제공하며, 컴파일한다.

 

 

 

 

2. 원하는 버전 다운로드

1) 아래 링크 접속

https://www.azul.com/

 

Home

Introducing Cloud Native Compiler Offload JIT compilation with the Cloud Native Compiler to enhance the performance of Java applications in any compute environment.

www.azul.com

 

Download Now 클릭

 

2) 원하는 버전 다운로드

아래로 내리다보면 버전이 내림차순으로 정렬되어 있습니다.

 

원하는 버전과 운영체제 확인 후 다운로드!

m1 macOS는 ARM 프로세서를 선택해야 합니다.

 

 

3. 설치 파일 실행시켜서 로컬에 설치

요건 그냥 설치하면 되니까 넘어가겠습니다.

 

 

 

 

 

3. 터미널에서 환경변수 설정

1) JDK 설치 경로 이동

cd /Library/Java/JavaVirtualMachines/

 

2) ls 커맨드로 JDK 폴더명 확인

3) 경로 복사

/Library/Java/JavaVirtualMachines/{zdk폴더명}/Contents/Home

예시 : /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home

 

4) bash_profile 편집

vi ~/.bash_profile

위 명령어를 입력하면 bash_profile 파일을 편집할 수 있습니다.

 

(커맨드 정리)

편집하기 : i

편집상태 끝내기 : esc

저장하고 나가기 : :wq 입력 후 엔터

위와 같이 수정해야 합니다.

JAVA_HOME 변수는 위에서 복사한 경로를,

PATH 변수는 위의 사진대로 수정해줍니다.

 

5) zshrc 편집

vi ~/.zshrc

위와 똑같이 추가해주면 됩니다.

(다른 환경변수가 이미 있을 수도 있습니다)

 

6) 환경변수 설정 변경 반영

source ~/.bash_profile
source ~/.zshrc

터미널에 위 명령어를 차례로 입력해줍니다.

 

7) Java 버전 확인

java -version

아래처럼 버전이 바뀐 것을 볼 수 있습니다.

 

 

자 그럼 이제,

위의 1번(IntelliJ JDK 버전 변경)으로 돌아가서

원하는 버전으로 바꿔주시면 끝입니다!!

 

고생하셨습니다 ^_^

 

 

 

 

 

반응형
반응형

구글에 '깃허브 리드미 꾸미기' 라고 검색하면 아주 많은 아티클들이 나옵니다.

좋은 아티클들이 많고, 저도 그를 보고 쉽게 따라했기에 저도 기여하고 싶은 생각이 들어 타자를 칩니다.

 

저는 시간이 없는 분들을 위한 초초초 간단 버전 리드미 꾸미기를 알려드리려고 합니다.

(결과물은 안 간단해요.. 예쁩니다.. 시간이 빠른 버전입니다..)

 

** 참고로 저는 html, css 하나도 모르는 백엔드 외골수입니다.

 

결과물은 아래 링크와 같습니다.

https://github.com/horsehair

 

horsehair - Overview

horsehair has 10 repositories available. Follow their code on GitHub.

github.com

부끄럽지만 대충 요런 느낌..

 

 

간단 버전에 앞서..

시간이 있으시다면, 뭐니뭐니 해도 공식문서 참고하시는 것을 추천드립니다.

https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme

 

Managing your profile README - GitHub Docs

About your profile README You can share information about yourself with the community on GitHub.com by creating a profile README. GitHub shows your profile README at the top of your profile page. You decide what information to include in your profile READM

docs.github.com

 

 

 

간단 버전 따라하기

정말 쉽습니다. 과정을 먼저 요약하겠습니다.

 

1. 리파지토리 만들기

2. 공개된 리드미 긁어 오기

3. 나에게 맞게 수정하기

 

 

1. 리파지토리 만들기

위의 주소에서(horsehair는 개인 아이디로) 오른쪽의 초록색 New 버튼을 클릭합니다.

 

본인 아이디와 동일하게 Repository name을 설정합니다.

(빨간 경고는, 제가 이미 동일한 이름의 리파지토리를 만들었기 때문에 발생하는 것으로 무시해주세요!)

 

아래 쪼꼬만 깃붕쓰가 horsehair/horsehair는 특별한 리파지토리라,

README.md를 추가하면 GitHub profile에 등록될 거라고 알려주네요!

 

 

Public, Add a README file 에 체크해주시고 

Create repository 하면 끝!

 

 

 

 

 

2. 공개된 리드미 긁어오기

어떤 리드미를 긁어오냐구요?

저의 리드미를 긁어가세요!

https://github.com/horsehair

 

horsehair - Overview

horsehair has 10 repositories available. Follow their code on GitHub.

github.com

위 링크 들어가시고, 아래 내용을 따라해주세요!

(소프트웨어는 어차피 오픈소스 생태계 아니겠습니다. 도움 받고 기여하고 선순환을 지속하려고 노력..)

 

리파지토리 탭에 들어가서, 가져갈 리드미의 유저 이름과 일치하는 리파지토리를 찾읍시다.

 

맨 위에 있군요! (오늘 수정해서..)

 

그럼 해당 리파지토리 리드미가, 아까 본 프로필 리드미와 일치하는 것을 볼 수 있습니다.

여기서 README.md 파일명을 클릭해줍니다.

 

Raw 버튼 클릭해서, 마크다운으로 변환된 버전이 아닌 Raw 버전의 코드를 보러 갑시다.

 

대충 이런 화면을 보실 수 있는데요,

전체 긁어 갑시다!

아래에서 대략 설명 드릴게요.

 

 

 

 

 

3. 나에게 맞게 수정하기

여기부터는, html과 마크다운에 익숙하시다면 읽으실 필요가 없습니다.

하지만 익숙하지 않은 분들을 위해.. 간단 설명을 드리겠습니다.

 

코드와 결과창을 비교하면, 어디가 어디를 나타내는지 알 수 있습니다.

 

어때요 간단하지 않은가요?

내용을 바꾸고 싶다면, 해당하는 위치의 텍스트를 찾아 바꾸면 됩니다.

 

맨 아래에 있는 WOOJIN's GitHub Stats는 아래 코드를 넣으시면 됩니다.

<div>
  <img height="170em" src="https://github-readme-stats.vercel.app/api?username=horsehair&show_icons=true&theme=gruvbox" align="center" />
</div> 
<br>

주의: username= 뒤에 horsehair는 본인 아이디로 수정해야 합니다.

그리고 theme= 뒤에 gruvbox를 수정하면 테마(색)이 변합니다.

github readme stats theme 검색하시면 많이 나올 겁니다!

 

 

마크다운 문법은 간단하니 넘어가고,

html 읽기가 어려우신 분들을 위해 사이트 하나를 소개합니다.

아래 사이트에 html 코드를 복붙하시면, 미리보기를 보실 수 있습니다.

http://www.cssdesk.com

 

CSSDesk - Online CSS Sandbox

HTML Hello World!

www.cssdesk.com

 

위처럼, 수정해보면서 감을 잡고

깃허브 리드미에 추가하시면 됩니다!

(폰트 깨지는 것은, 해당 사이트 들어가면 보이는 CSS 코드를 지웠기 때문입니다. (오류가 좀 나서))

 

 

 

+) 여러가지 뱃지, 사용한 언어 비율 등

다양한 활용은 깃허브 리드미 뱃지, 깃허브 리드미 사용 언어 등으로 검색하시면 잘 나와 있습니다!

 

 

 

궁금하신 점은 댓글 달아주시면 가능한 도움 드리겠습니다!

감사합니다.

 

 

 

 

 

 

 

 

 

반응형
반응형

아티클의 제목과 같은 에러가 발생했는데, 전문은 아래와 같다.

 

 

Logger로 기록한 error

[Nest] 64896  - 2022. 10. 13. 오후 8:00:56   ERROR [ExceptionHandler] Nest can't resolve dependencies of the ScriptService (FirstRepository, SecondRepository, ThirdRepository, ?). Please make sure that the argument SentenceRepository at index [3] is available in the ScriptModule context.

Potential solutions:
- If SentenceRepository is a provider, is it part of the current ScriptModule?
- If SentenceRepository is exported from a separate @Module, is that module imported within ScriptModule?
  @Module({
    imports: [ /* the Module containing SentenceRepository */ ]
  })

 

 

에러 내용 해석

Nest가 ScriptService에 ?에 해당하는 것의 의존성 주입을 할 수 없다는 뜻이다.

나는 Potential solutions 중 첫번째에 해당하는 간단한 오류였다.

ScriptModule에 SentenceRepository를 import하지 않고, ScriptService의 생성자에 추가했기 때문에 발생한 오류다.

 

 

 

해결 방법

// script.module.ts

@Module({
  imports: [
    TypeOrmModule.forFeature([
      ScriptRepository, ScriptExampleRepository, UserRepository, NewsRepository
    ]),
  ],
  controllers: [ScriptController],
  providers: [ScriptService, JwtModule]
})
export class ScriptModule {}

위와 같이 module에, service에서 사용한 repository를 import함으로써

의존성 주입에서 발생한 error를 수정할 수 있었다.

 

 

 

 

반응형
반응형

User와 News 사이에 즐겨찾기(Favorite)기능을 구현하고자 한다.

ManyToMany 관계를 설정하고

특정 API에 user와 news 정보를 보내면 관계가 추가되는 기능을 구현해야 한다.

 

1. 관계를 설정하고 (기본, lazy, eager 설명)

2. 기능을 구현하기까지 과정을 정리해보겠다. (lazy 관계 사용)

 

 

 

ManyToMany 관계 설정

관계는 아래와 같이 설정했다.

// user.entity.ts
  @ManyToMany(() => News, (news) => news.favorites)
  @JoinTable()
  favorites: Promise<News[]>;
// news.entity.ts
  @ManyToMany(() => User, (user) => user.favorites)
  favorites: User[]

여기서 드는 의문은,

favorites의 타입이 왜 Promise 형태인지이다. (이는 lazy 설정을 사용하기 위함이다!)

 

TypeORM에서 ManyToMany를 구현하는 형식은 세 가지가 있는데,

1. 기본 설정

2. lazy 관계

3. eager 관계 이다.

 

아래에서 각각의 설정에 대해 설명해보고, 필자가 왜 lazy 관계를 사용했는지도 설명할 것이다.

 

 

 

1. 기본 설정

기본 설정은 아래와 같이 관계를 설정한다.

// user.entity.ts
  @ManyToMany(() => News, (news) => news.favorites)
  @JoinTable()
  favorites: News[];
// news.entity.ts
  @ManyToMany(() => User, (user) => user.favorites)
  favorites: User[]

위와 같은 관계에서,

User를 초기 생성할 때 favorites을 선언하는 케이스는 예시가 많이 나온다.

 

const category1 = new Category()
category1.name = "animals"
await dataSource.manager.save(category1)

const category2 = new Category()
category2.name = "zoo"
await dataSource.manager.save(category2)

const question = new Question()
question.title = "dogs"
question.text = "who let the dogs out?"
question.categories = [category1, category2]
await dataSource.manager.save(question)

위의 예시는 TypeORM docs에서 발췌한 코드인데,

역시 선언하고 저장하는 형식이다.

 

그런데.. 이미 저장된 favorites을 불러와 정보를 추가하는 로직은

도저히 예시를 찾을 수가 없는 것이다.

그러다 발견한 것이 아래 방식이다!

 

 

 

 

2. eager 관계

// user.entity.ts
  @ManyToMany(() => News, (news) => news.favorites, {
    eager: true,
  })
  @JoinTable()
  favorites: News[];
// news.entity.ts
  @ManyToMany(() => User, (user) => user.favorites)
  favorites: User[]

위와 같이 관계를 설정하면,

어느 한 쪽 정보를 조회 시, favorites에 리스트로 저장된 반대편 정보도 함께 조회된다.

 

하지만, 필요하지 않은 경우에도 (많을지도 모르는 양의) 반대편 정보를 조회해야 한다는 단점이 있다.

 

 

 

 

 

3. lazy 관계

// user.entity.ts
  @ManyToMany(() => News, (news) => news.favorites)
  @JoinTable()
  favorites: Promise<News[]>;
// news.entity.ts
  @ManyToMany(() => User, (user) => user.favorites)
  favorites: User[]

 

lazy 관계를 맺으면, 평소에는 서로의 정보를 저장하지 않고

참조 시에만 불러오는 형식을 취한다.

 

즉, User의 입장에서

favorites을 조회하지 않는(News를 참조하지 않는) 경우에는 favorites에 정보가 저장되지 않고,

favorites을 조회하는(News를 참조하는) 경우에는 favorites에 정보가 저장된다.

 

이 정보는 user_favorite_news라고 하는 새로 생성된 Join 테이블에서 가져 온다.

 

lazy 관계를 사용하는 방식은, 위에서처럼 관계를 Promise로 정의하면 된다.

꺼내서 사용하는 경우에도 Promise로 다뤄줘야 하는데,

이는 아래에서 기능을 구현할 때 다시 언급하겠다.

 

 

 

 

기능 구현!

위에서 언급한 대로,

User가 가지고 있는 favorites(News의 리스트)에 원하는 News를 넣는 기능을 구현해야 한다.

그래서 아래와 같이 구현했다!

 

// user.repository.ts
    async addFavoriteNews(user: User, news: News): Promise<User> {
      const favorites = await user.favorites;
      favorites.push(news);
      user.save();
      return user;
    }
    
    async deleteFavoriteNews(user: User, news: News): Promise<User> {
      let favorites = await user.favorites;
      const newsId: number = news.id;

      user.favorites = Promise.resolve(
        favorites.filter((news) => {
          return news.id !== newsId;
        }),
      );

      user.save();
      return user;

    }

user.favorites은 Promise 객체이므로 await으로 불러와야 함에 주의해야 한다.

또한, 위와 같이 수정 시에도 Promise.resolve 형태로 사용해야 한다!

 

그 점만 주의한다면,

- 참조 시에만 데이터를 불러와 경제적이고,

- API 호출 시마다 관계를 추가할 수 있는

좋은 기능을 구현할 수 있었다!

 

위에서 return한 user를 response하면 아래와 같다!

{
    "status": 200,
    "success": true,
    "message": "좋아하는 뉴스 토글 성공",
    "data": {
        "socialId": "123",
        "nickname": "test",
        "__favorites__": [
            {
                "title": "Test title3",
                "category": "사회",
                "id": 3
            },
            {
                "title": "Test title4",
                "category": "연예",
                "id": 4
            }
        ],
        "__has_favorites__": true
    }
}

(status, success, message는 임의로 정한 규격이니 무시해도 좋다.)

__favorites__, __has_favorites__라는 속성으로 표현된다!

 

뭐니뭐니해도 공식문서가 짱이다.

 

 

 

 

참고 자료 :

https://orkhan.gitbook.io/typeorm/docs/eager-and-lazy-relations

 

Eager and Lazy Relations - typeorm

Note: if you came from other languages (Java, PHP, etc.) and are used to use lazy relations everywhere - be careful. Those languages aren't asynchronous and lazy loading is achieved different way, that's why you don't work with promises there. In JavaScrip

orkhan.gitbook.io

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
반응형

문제 링크

https://www.acmicpc.net/problem/10989

 

10989번: 수 정렬하기 3

첫째 줄에 수의 개수 N(1 ≤ N ≤ 10,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 10,000보다 작거나 같은 자연수이다.

www.acmicpc.net

문제

N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 10,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 10,000보다 작거나 같은 자연수이다.

출력

첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한 줄에 하나씩 출력한다.

예제 입력 1

10
5
2
3
1
4
2
3
5
1
7

예제 출력 1

1
1
2
2
3
3
4
5
5
7

 

 

 


틀린 풀이

import sys

n = int(sys.stdin.readline().rstrip())
array = []

for _ in range(n):
    array.append(int(sys.stdin.readline().rstrip()))

for _ in range(n):
    for i in range(n - 1):
        if array[i] > array[i + 1]:
            array[i], array[i + 1] = array[i + 1], array[i]

for number in array:
    print(number)

이유

  • 메모리 초과
    • 메모리를 줄이려고 버블 정렬을 써가며 별짓을 다 했으나, 10,000,000 크기의 리스트를 줄일 수 없어 시실패하였다.

 

 

맞은 풀이1

import sys
n = int(sys.stdin.readline().rstrip())
count_array = [0] * 10001

for i in range(n):
    count_array[int(sys.stdin.readline().rstrip())] += 1

for i in range(10001):
    if count_array[i] != 0:
        for j in range(count_array[i]):
            print(i)

접근 방식

  • 계수 정렬을 사용!
    • 입력값의 범위가 10,000 이하이므로, 리스트의 크기가 10,000,000에서 10,000으로 줄어든다.

 

 

정리

  • 계수 정렬의 존재와 사용 방법을 기억하자.
반응형
반응형

문제 링크

https://www.acmicpc.net/problem/2108

 

2108번: 통계학

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

www.acmicpc.net

문제

수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

출력

첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

둘째 줄에는 중앙값을 출력한다.

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

넷째 줄에는 범위를 출력한다.

예제 입력 1

5
1
3
8
-2
2

예제 출력 1

2
2
1
10

예제 입력 2

1
4000

예제 출력 2

4000
4000
4000
0

예제 입력 3

5
-1
-2
-3
-1
-2

예제 출력 3

-2
-2
-1
2

예제 입력 4

3
0
0
-1

예제 출력 4

0
0
0
1

(0 + 0 + (-1)) / 3 = -0.333333... 이고 이를 첫째 자리에서 반올림하면 0이다. -0으로 출력하면 안된다.

 

 

 

 


내 풀이

import sys
from collections import Counter

n = int(sys.stdin.readline().rstrip())

array = []
for i in range(n):
    array.append(int(sys.stdin.readline().rstrip()))

array.sort()

s = sum(array)
max_number = max(array)
min_number = min(array)
length_array = len(array)

# 최빈값 구하는 로직
counter = Counter(array)
mode = counter.most_common() # 숫자:빈도 를 나타내는 튜플을 빈도 순으로 나열
mode = [i for i in mode if i[1] == mode[0][1]] # 빈도수가 최빈값과 같은 튜플들만 남긴다
mode_result = []

# 빈도가 아닌 숫자만 남긴다
for i in mode:
    mode_result.append(i[0])

mode_result.sort() # 정렬

# 최빈값이 2개 이상이면 2번째로 작은 수를, 아니면 최빈값을 저장한다.
if len(mode_result) >= 2:        
    mode_number = mode_result[1]
else:
    mode_number = mode_result[0]

# 출력
print(round(s / n))
print(array[length_array // 2])
print(mode_number)
print(max_number - min_number)

접근 방식

  • 평균, 중앙값, 길이는 쉬우니까 pass
  • 최빈값은 Counter 라이브러리의 most_common() 모듈을 사용하였다.
    • [1, 1, 1, 2, 3, 3, 3] 을 [(1, 3), (3, 3), (2, 1)] 로 바꿔주는 라이브러리
    • 잘 조작하여 조건에 맞는 최빈값을 구하였다.

 

 

남의 풀이

import sys
from collections import Counter
n = int(sys.stdin.readline())
nums = []
for i in range(n):
    nums.append(int(sys.stdin.readline()))
nums.sort()
nums_s = Counter(nums).most_common()
print(round(sum(nums) / n))
print(nums[n // 2])
if len(nums_s) > 1:
    if nums_s[0][1] == nums_s[1][1]:
        print(nums_s[1][0])
    else:
        print(nums_s[0][0])
else:
    print(nums_s[0][0])
print(nums[-1] - nums[0])

접근 방식

  • 다른 것은 볼 필요 없고, 최빈값 출력하는 로직만 보면 된다.
  • 비슷한 로직인데, Counter 객체를 출력할 때 더 간결하게 사용하였다.
    • 숫자 리스트 길이가 2 이상일 때, 첫번째 빈도와 두번째 빈도가 같다면 두번째 숫자를 출력
    • 첫번째 빈도가 더 크다면, 첫번째 숫자를 출력!

 

 

정리

  • 최빈값과 빈도를 다룰 때는 Counter 라이브러리를 잘 사용해야 한다!
  • Counter.most_common() 을 사용하는 방법에 대해 알 수 있었다.
반응형
반응형

문제 링크

https://www.acmicpc.net/problem/1929

문제

M이상 N이하의 소수를 모두 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 M과 N이 빈 칸을 사이에 두고 주어진다. (1 ≤ M ≤ N ≤ 1,000,000) M이상 N이하의 소수가 하나 이상 있는 입력만 주어진다.

출력

한 줄에 하나씩, 증가하는 순서대로 소수를 출력한다.

예제 입력 1

3 16

예제 출력 1

3
5
7
11
13

 

 

 

 

 


틀린 풀이

n, m = map(int, input().split())

start_time = time.time()
# 2 ~ m의 리스트
array = list(range(2, m + 1))
array = [2] + [i for i in array if i % 2 == 1] # 2와 3 이상의 홀수만 남긴다

index = 0
while True:
		# 걸리지고 남은 맨 앞의 수부터 차례로 골라, 뒤에 있는 수를 나눠 소수를 판별한다 (에라토스테네스의 체)
    array = array[0:index + 1] + [i for i in array[index + 1:] if i % array[index] != 0]
    index += 1
		# 끝까지 다 진행한 경우 종료
    if index >= len(array):
        break
		# 사실 여기 올 일이 없음
    if array[index] >= m:
        break

# 위에서 2 ~ m 리스트로 시작했으니
# n 이상인지 판별하여 남긴다
result = [i for i in array if n <= i]
for number in result:
    print(number)

end_time = time.time()
print(end_time - start_time)

이유

  • 시간초과
  • 에라토스테네스의 체를 사용했으나, 시간복잡도가 너무 크다.

 

 

맞은 풀이1 (시간복잡도 상으로는 틀려야 한다..)

import time

start_time = time.time()
def check_prime(number):
    if number == 1:
        return False
    else:
        for i in range(2, int(number ** 0.5 + 1)):
            if number % i == 0:
                return False
        return True

n, m = map(int, input().split())

for i in range(n, m + 1):
    if check_prime(i) == True:
        print(i)
end_time = time.time()

print(end_time - start_time)

접근 방식

  • n이 소수인지 판별하려면, 1 ~ root(n) + 1 까지의 수로 나누어보면 된다.
  • → 약수를 대칭을 이루므로, root(n) + 1 까지 나누어떨어지지 않는다면, 그 이상의 수로 나누어떨어질 일이 없기 때문.
  • 해당 방식이 작은 수에는 더 많은 시간이 소요되지만, 큰 수에 대해서는 훨씬 적은 시간이 소요된다.
  • 시간 복잡도 : O(N*N^0.5) → 10억 번의 연산으로 시간초과가 맞아 보인다..

 

 

 

맞은 풀이2

n, m = map(int, input().split())

start_time = time.time()
array = list(range(2, m + 1))
array = [2] + [i for i in array if i % 2 == 1]

index = 0
while True:
    array = array[0:index + 1] + [i for i in array[index + 1:] if i % array[index] != 0]
    index += 1
    if index >= len(array):
        break
    if array[index] >= m ** 0.5 + 1:
        break

result = [i for i in array if n <= i]
for number in result:
    print(number)

end_time = time.time()
print(end_time - start_time)

접근 방식

  • 에라토스테네스의 체를 이용한 풀이
  • 에라토스테네스의 체를 사용할 때, 맞은 풀이1 처럼 m의 제곱근까지만 배수를 제거하였다. (그 이상의 배수는 존재하지 않는다! 이미 그 이하 수의 배수를 제거할 때 없어졌기 때문!)
  • (연산이 간결해져서 훨씬 빠르다..)

 

 

맞은 풀이3

def prime_list(n):
    # 에라토스테네스의 체 초기화: n개 요소에 True 설정(소수로 간주)
    sieve = [True] * n

    # n의 최대 약수가 sqrt(n) 이하이므로 i=sqrt(n)까지 검사
    m = int(n ** 0.5)
    for i in range(2, m + 1):
        if sieve[i] == True:           # i가 소수인 경우
            for j in range(i+i, n, i): # i이후 i의 배수들을 False 판정
                sieve[j] = False

    # 소수 목록 산출
    return [i for i in range(2, n) if sieve[i] == True]

M, N = map(int, input().split())

N += 1
sieve = [True] * N
for i in range(2, int(N**0.5)+1):
    if sieve[i]:
        for j in range(2*i, N, i):
            sieve[j] = False
for i in range(M, N):
    if i > 1:
        if sieve[i]:
            print(i)

접근 방식

  • 에라토스테네스의 체를 이용한 풀이
  • 맞은 풀이2 를 보다 깔끔하게 정리한 풀이
  • 실제 소수의 리스트를 남기는 것이 아니라, 1 ~ m(해당 코드에서는 n)까지의 True리스트를 만들고, 1 ~ squr(m) + 1의 배수에 해당하는 인덱스의 값을 False로 바꿨다.

 

 

 

정리

  • 대량의 소수를 찾아야 한다!
    1. 에라토스테네스의 체 사용
    2. 1 ~ m 이 아닌, 1 ~ sqrt(m) + 1 까지만 배수를 제거하면 된다!
반응형

+ Recent posts