728x90

Controller 를 만들어주었다. @GetMapping 으로 받았는데 url 뒤에 query 문이 생겼고, 이는 RequestParam 을 받을 때 자동으로 생긴다고 이해했다. 다음에 다시 확인을 해 볼 계획이다. 

 

@GetMapping 으로 받은 후 우선 존재하는 스터디룸인지 확인을 해준다. 존재 한다면, 룸 이름과 리뷰를 Model 로 담아 view 로 넘겨주었다. 

 

// 스터디룸 설명 변경
@GetMapping("/admin/change") // url 뒤에 change_name 이 붙는지?
public String GetChangeRoom(@RequestParam("change_name") String change_name, Model model){

changeReview changeReview = new changeReview(roomRepository);

// 존재하지 않는 스터디 룸인 경우

if(changeReview.exist(change_name)==false){
model.addAttribute("change_fail","존재하지 않는 스터디 룸 입니다.");
return "admin/alert/change_fail";
}

// 존재하는 스터디 룸인 경우

List rooms = roomRepository.findByroomName(change_name);
room room = (StudyRoom.StudyRoom.entity.room) rooms.get(0);

model.addAttribute("roomName",change_name);
model.addAttribute("roomInformation",room.getRoomInformation());

return "admin/change";
}

 

 

 

 

 

 

@PostMapping 으로는 룸 이름과 리뷰를 받아주었고, changeReview 라는 Service를 이용해서 변경을 해주었다. 일부러 Service 패키지를 이용하기 위해 분리를 시켰다. 

 

 


@PostMapping("/admin/change")
@Transactional
public String PostChangeRoom(@RequestParam("roomName") String roomName, @RequestParam("roomInformation") String roomInformation){

changeReview changeReview = new changeReview(roomRepository);
changeReview.changeReview(roomName,roomInformation);



return "redirect:/admin";
}

}

 

 

 

 

 

 

 

아래 클래스를 이용해서 리뷰의 수정이 이루어지도록 해주었다. Casting 을 통해 room 객체로 변경해주었고, 리뷰 속성의 @Setter을 이용해 변경할 수 있도록 해주었다. 

 

 


@RequiredArgsConstructor
public class changeReview {

final roomRepository roomRepository;
public boolean exist(String changeName) {

if(roomRepository.findByroomName(changeName).isEmpty()==true){
           return false;
}
else {
          return true;
}

}

@Transactional
public void changeReview(String roomName,String roomInformation) {

List rooms = roomRepository.findByroomName(roomName);
StudyRoom.StudyRoom.entity.room room = (StudyRoom.StudyRoom.entity.room) rooms.get(0);

room.setRoomInformation(roomInformation);


}
}

 

 

 

Test 를 통해 검증을 해주었고 이상 없이 테스트는 성공했다.

 

 


@SpringBootTest
@Transactional
public class reviewChangeTest {

@Autowired roomRepository roomRepository;

@Test
void 리뷰_변경_성공() {

// given
roomDto roomDto = new roomDto(roomRepository);
String roomName = "test123";
roomDto.create_room(roomName,10L,15000L,"리뷰 변경 전");

// when
changeReview changeReview = new changeReview(roomRepository);

String newReview = "리뷰 변경 후";
changeReview.changeReview(roomName,newReview);

List test = roomRepository.findByroomName(roomName);

room room = (StudyRoom.StudyRoom.entity.room) test.get(0);

// then

Assertions.assertThat(test.isEmpty()==false);
Assertions.assertThat(room.getRoomInformation()).isEqualTo("리뷰 변경 후");


}


}

 

728x90
728x90

dp를 이용하려고 했으나 방법을 몰랐고, product 를 이용했다. 사실 무조건 메모리 초과나 시간 초과가 나는데 숫자가 작아서 성공했다.

import sys
from collections import deque
from itertools import product
 
 
num = int(input())
 
def check(n): 
 
    '''
    # 가능한 1,2,3 개수 찾아서 permutations 돌리기
 
    three = n//3
 
    n = n-(three*3)
 
    two = n//2
 
    n = n-(n//2)
 
    one = n
 
    '''
    num = [1,2,3]
 
    answer = 0
 
    for i in range(1,n+1):
        k = list(product(num, repeat = i))
 
        for i in range(0,len(k)):
            if sum(k[i]) == n:
                answer+=1
 
 
    return answer
 
 
for i in range(num):
    k = int(input())
    print(check(k))
 
 
728x90
728x90

우선은 product 를 이용했고 예상했다시피 메모리 초과가 나왔다. 구글링을 통해 보니, 첫 집의 나머지 두개를 최댓값으로 변경해주는 방식으로 해결할 수 있었고, 이를 이요해서 풀었다.

import sys
from collections import deque
from itertools import product
import copy
 
 
num = int(input())
 
ks = [ ]
 
for i in range(num):
    ks.append(list(map(int,sys.stdin.readline().split(" "))))
 
 
'''
a = [0,1,2]
 
m = list(product(a,repeat=num))
 
index = [ ] 
 
def check(k):
 
    if k[0]==k[-1]:
        return False
 
    for i in range(0,len(k)-1):
        if k[i]==k[i+1]:
            return False
    return True
 
def find(k,temp):
    answers = 0
 
    for i in range(0,len(temp)):
 
        answers+=k[i][temp[i]]
 
    return answers
 
 
answer = [ ]
 
for i in range(0,len(m)):
    if check(list(m[i]))== True:
 
        answers = 0
 
        answer.append((find(k,list(m[i]))))
 
 
 
print(min(answer))
 
'''
answer = [ ]
 
k = copy.deepcopy(ks)
 
k[0][1] = 1000000000
k[0][2] = 1000000000
 
 
for i in range(1,len(k)):
 
    k[i][0] += min(k[i-1][1],k[i-1][2])
    k[i][1] += min(k[i-1][0],k[i-1][2])
    k[i][2] += min(k[i-1][0],k[i-1][1])
 
answer.append(min(k[-1][1],k[-1][2]))    
 
 
k1 = copy.deepcopy(ks)
 
k1[0][0] = 1000000000
k1[0][2] = 1000000000
 
 
for i in range(1,len(k1)):
 
    k1[i][0] += min(k1[i-1][1],k1[i-1][2])
    k1[i][1] += min(k1[i-1][0],k1[i-1][2])
    k1[i][2] += min(k1[i-1][0],k1[i-1][1])
 
answer.append(min(k1[-1][0],k1[-1][2]))           
 
k2 = copy.deepcopy(ks)
 
k2[0][0] = 1000000000
k2[0][1] = 1000000000
 
 
for i in range(1,len(k2)):
 
    k2[i][0] += min(k2[i-1][1],k2[i-1][2])
    k2[i][1] += min(k2[i-1][0],k2[i-1][2])
    k2[i][2] += min(k2[i-1][0],k2[i-1][1])
 
answer.append(min(k2[-1][0],k2[-1][1]))  
 
print(min(answer))
 
 
 
 
 
 
728x90
728x90

W3C의 Html Checker 를 통해 Html 문서를 검증할 수 있다.

W3schools 에서 다양한 언어를 공부할 수 있다.

< 기본 cmd 명령어 > 

cd : 경로 이동
md: 폴더 만들기

< meta > 태그

- 해당 문서에 대한 정보인 메타데이터를 정의할 때 사용한다.
- <head> 요소 내부에 위치해야 한다.
- heyword, description, author, redirect 등의 설정이 가능하다


< 시맨틱 웹 >

- 태그 자체가 의미를 가지게 해서 문서 구조, 내용을 정확하게 파악할 수 있다.
header, footer, article, aside, nav, section 등의 종류가 있다.


<div> -> 블록 태그로 한 줄 전체를 차지한다.
<span> -> 인라인 태그로 글자 크기만큼만 자리를 차지한다.

<ol> -> 번호 있는 목록
<ul> -> 번호 없는 목록
<li> -> <ol> 과 <ul> 태그의 항목을 만든다.


Lorem Ipsum 사이트를 통해 임의의 문장 생성이 가능하다.

실무에서는 img 태그 대신 css background 를 이용하는 추세이다.

Iframe : 웹문서 안에 다른 웹문서를 넣을 수 있다.

728x90

'🟢 디지털 하나路 > Architecture' 카테고리의 다른 글

금융 서비스의 이해  (0) 2023.05.04
하나은행 특강  (0) 2023.05.02
728x90

시간이 아주 오래 걸렸지만 정답이 되었다. 두 가지 경우로 나누어준 후 bfs 를 돌려주었다. 플로이드 워셜 알고리즘을 사용하는 문제라고 한다.

import sys
from collections import deque
 
n = int(input())
m = int(input())
 
k = [ ]
 
for i in range(m):
    k.append(list(map(int,sys.stdin.readline().split(" "))))
 
k = list(sorted(k))
 
 
def check(k,num,n):
 
    visited = [0] * (n+1)
 
    visited[0] = 1
    visited[num] = 1
 
    queue = deque()
 
    # i 로 시작하는 걸로 반복문 돌리기
 
    for i in range(0,len(k)):
        if k[i][0] == num:
            queue.append(k[i][1])
 
    while queue:
        x = queue.popleft()
 
        visited[x] = 1
 
        for i in range(0,len(k)):
            if k[i][0] == x and visited[k[i][1]] == 0:
                queue.append(k[i][1])
 
 
# i 로 끝나는 걸로 반복문 돌리기
 
    queue1 = deque()
 
    for i in range(0,len(k)):
        if k[i][1] == num:
            queue1.append(k[i][0])
 
    while queue1:
        x = queue1.popleft()
 
        visited[x] = 1
 
        for i in range(0,len(k)):
            if k[i][1] == x and visited[k[i][0]] == 0:
                queue1.append(k[i][0])
 
    print(visited.count(0))
 
for i in range(1,n+1):
    check(k,i,n)
 
728x90
728x90

컨트롤러에서 삭제 기능을 구현했지만, 서비스와 컨트롤러를 분리하게 위해 리팩토링 했다.

 

 

 

 

 

컨트롤러를 구현했다. 스터드 룸의 id 보다 이름으로 제거하는 게 실용성이 있다고 생각해서 이름을 파라미터로 받았다. removeRoom 의 boolean 값으로 제거의 유무를 판단했다. 제거 기능은 모두 removeRoom으로 넘겨주었다. boolean 값에 따라 model 에 알맞은 message 를 담아주어 view 로 넘겨주었다.

 

// 스터디룸 제거
@PostMapping("/admin/remove")
public String RemoveRoom(@RequestParam("remove_name") String remove_name,Model model){

removeRoom removeRoom = new removeRoom(roomRepository);

// 존재하지 않는 룸이면

if(removeRoom.removeRoom(remove_name)==false){

model.addAttribute("remove_fail","존재하지 않는 스터디 룸 입니다.");
return "admin/remove_fail";
}

// 룸 정상 제거 시
else{
model.addAttribute("remove_success",remove_name + " 룸이 제거되었습니다.");
return "admin/remove_success";
}

}

 

 

 

 

 

 

removeRoom 클래스이다. 삭제할 룸이 존재하는지 여부를 판단 후, boolean 값을 return 해준다. 룸이 존재하면 이를 삭제해준다.

 

@RequiredArgsConstructor
public class removeRoom {

final roomRepository roomRepository;
public boolean removeRoom(String remove_name){

boolean remove = false;

// 존재하지 않는 룸이면
if(roomRepository.findByroomName(remove_name).isEmpty()==true){
return false;
}

// 룸 정상 제거 시
else{
List room = roomRepository.findByroomName(remove_name);
roomRepository.delete((StudyRoom.StudyRoom.entity.room) room.get(0));

return true;
}
}
}

 

 

 

 

 

 

룸 제거 기능 테스트를 만들었고 이상 없이 돌아간다. 기본적인 기능 말고 추가적으로 난이도 있는 기능을 기획하고 구현해야 겠다.

 

@SpringBootTest
public class roomRemoveTest {
@Autowired
StudyRoom.StudyRoom.repository.roomRepository roomRepository;


// 스터디 룸이 정상적으로 제거 되는 경우

@Test
void _제거_성공() {

// given
roomDto roomDto = new roomDto(roomRepository);
String roomName = "test123";
roomDto.create_room(roomName,10L,15000L,"test room 입니다");

// when
removeRoom removeRoom = new removeRoom(roomRepository);

// then

Assertions.assertThat(removeRoom.removeRoom(roomName)==true);
Assertions.assertThat(roomRepository.findByroomName(roomName).isEmpty()==true);


}

// 제거할 스터디 룸이 존재하지 않는 경우
@Test
void _제거_실패() {

// given
String roomName = "test123";
// when
removeRoom removeRoom = new removeRoom(roomRepository);

// then

Assertions.assertThat(roomRepository.findByroomName(roomName).isEmpty()==false);


}

}

 

 

 

 

 

 

타임리프를 통해 관리자 페이지에 현재 존재하는 룸들을 표시해주었다.

 


<table class="room">
<p>
<tr>
<td>id</font></td>
<td></td>
<td>이름</td>
<td></td>
<td>수용 인원</td>
<td></td>
<td>가격</td>
<td></td>
<td>설명</td>



</tr>

<tr th:each="room : ${room}">
<td th:text="${room.roomId}"></td>
<td></td>
<td th:text="${room.roomName}"></td>
<td></td>
<td th:text="${room.roomPerson}"></td>
<td></td>
<td th:text="${room.roomPrice}"></td>
<td></td>
<td th:text="${room.roomInformation}"></td>
<td></td>

</tr>
</table>

728x90
728x90

조합을 이용했고 당연히 메모리 초과가 났다. 힌트 글에서 최대 증가 수열을 구하면 된다고 했고 저번에 풀었던 풀이지만 기억이 안났다. 이제는 이해가 됐고, 이를 이용해서 문제를 풀었다.

import sys
from collections import deque
from itertools import combinations
 
N = int(input())
 
k = [ ]
 
for i in range(N):
    k.append(int(input()))
 
 
# 앞에서 부터 최대 증가 하는 수 찾기
'''
def checks(k):
 
    for i in range(0,len(k)-1):
        if k[i]>k[i+1]:
            return False
    return True
 
check = 0
 
for i in range(N,-1,-1):
 
    if check == 1:
        break
 
    m = list(combinations(k,i))
 
    for j in range(0,len(m)):
        if checks(m[j]) == True:
            print(len(k)-len(m[j]))
            check = 1
            break
 
'''
 
dp = [1]*N
 
for i in range(len(k)):
    for j in range(i):
        if k[i] > k[j]:
            dp[i] = max(dp[i], dp[j]+1)
print(len(k)-max(dp))
 
728x90
728x90

이 문제를 풀려고 하는 방향은 맞았으나, 크루스칼 알고리즘을 몰라서 못풀었다. 구글링을 통해 해결을 했는데 아직 익숙하지는 않다.

import sys
from collections import deque
import copy
 
def union(x,y):
    x = find(x)
    y = find(y)
 
    if x<y:
        parent[y] = x
    else:
        parent[x] = y
 
 
def find(x):
    if x!= parent[x]:
        parent[x] = find(parent[x])
    return parent[x]
 
 
n = int(input())
m = int(input())
 
k = []
for i in range(m):
 
    a,b,c = map(int,input().split())
    k.append((c,a,b))
 
k.sort(reverse = True)
 
parent = [i for i in range(n+1)]
 
 
r,cnt = 0,0
while cnt != n-1:
    w,a,b = k.pop()
    if find(a) == find(b):
        continue
 
    union(a,b)
    r += w
    cnt += 1
 
print(r)
 
728x90

+ Recent posts