파이썬2021. 6. 17. 14:04
728x90

pdftotree를 이용해서 pdf를 html(tree구조)로 변경해야 하는 일이 있었다.

하지만 잘 쓰이지 않는지 코드가 나와있는 블로그가 거의 없었다.

나와 같이 헤멨던 분들에게 이 글이 도움이 되었으면 좋겠다. (도움이 되면 공감버튼 꾹!!)

 

[ pdftotree 깃허브 ]

https://github.com/HazyResearch/pdftotree

 

HazyResearch/pdftotree

:evergreen_tree: A tool for converting PDF into hOCR with text, tables, and figures being recognized and preserved. - HazyResearch/pdftotree

github.com

(사실 봐도 잘 모르겠다.. 설치 방법 외에는..)

 

 

* pycharm에서 install을 했더니 잘 되지 않는 것 같아 jupyter notebook을 이용했다.

(이용방법은 더보기 참고)

더보기

--------------------(더보기)--------------------

[jupyter notbook 이용해서 하는 법]

 

우선 anaconda prompt를 실행한다.

 

 

jupyternotebook을 실행하고 싶은 폴더로 이동 후 실행한다.

그리고 이 폴더에 변환 할 pdf파일을 넣을 것이다.

#원하는폴더로 이동
(base) C:\Users\min>cd 폴더명

# jupyter notebook 실행
(base) C:\Users\min\jupyter>jupyter notebook
나는 이름을 그냥 jupyter로 했는데 폴더명은 마음대로 해도 된다

 

코드를 입력하고 엔터치면 새 인터넷 창이 뜨면서 jupyter notebook이 실행된다.

 

여기 보이는 ipynb 파일을 클릭해서 코드를 입력해주면 된다.

 

코드 입력 후 Ctrl+Enter를 누르면 해당 셀이 실행된다.

--------------------(더보기)--------------------

 

 

1) pdf 준비

* hwp(한글)파일을 이용할 때는 을 이용하자! (추천사이트 https://allinpdf.com/hwp-to-pdf )

한글프로그램에서 pdf로 출력/저장 이렇게 해서 pdf를 만들면 에러가 많이 발생하는 것 같다.

 

준비한 pdfjupyter notebook 파일(ipynb)이 있는 폴더에 넣는다. (위의 예시에서는 C:\Users\min\jupyter )

 

 

 

2) pdftotree 코드 실행

 

pdftotree 설치

pip install pdftotree

 

import 해오기

import pdftotree

* pip install pdftotree와 import pdftotree는 따로 하는 걸 추천한다.

   jupyter notebook(아래참고)에서 같은 셀에 하면 에러가 발생하기도 함.

이렇게 따로 실행시키는 것을 추천한다.

코드

f_name='파일이름' #확장자는 필요없음
f_name_pdf=f_name+'.pdf'
#table을 포함 한 문서의 경우 model_type='table'로 해주는게 좋음
result = pdftotree.parse(f_name_pdf,html_path=None, model_type='table',model_path=None,visualize=False)

# 변경할 html 파일이름 생성
f_name_html=f_name+'.html'

# 유니코드 문제 해결
with open('out.html','w',-1,'utf-8') as f:
    f.write(result)
    
#전처리 코드(테이블 가시성 높임)
import re
file = open('out.html', 'r', encoding='utf-8')
text = file.read()

text = text.replace('\\n\\t', ' ')
text = text.replace('\\t', '')

text = text.replace('<table', '<table border=\'1\'')

new_file = open(f_name_html, 'w', encoding='utf-8')
new_file.write(text)
new_file.close()

file.close()

 

---------------------------------------------

 

약간 파일 이름을 하나하나 입력하기가 귀찮아서

폴더 내에 있는 파일들을 list로 읽어와서 변환해주는 코드를 짜봤다.

 

[ 폴더 내 pdf파일들을 html로 전환하기 ]

#-------를 기준으로 jupyternotebook에서 셀을 나눴다.

# pdftotree설치
pip install pdftotree
#-------------------------------------------
#import 해주기
import pdftotree
#-------------------------------------------

# [파일 이름 읽어오기]
import os
#path_dir할 때 \ -> / 바꿔주기
#이 코드가 위치 한 디렉토리로 설정해주기!
path_dir='C:/Users/min/jupyter'
file_list=os.listdir(path_dir)
print(file_list)
#-------------------------------------------

# [ pdf 파일만 골라서 html로 ]
for f_name_pdf in file_list:
    idx=file_list.index(f_name_pdf)    
    
    # 파일명 (.pdf) '' 인 것들만 고르기!
    fn=f_name_pdf.split('.pdf')
    if(len(fn)<2 or fn[1]!=''): # .oldPdf 이렇게 확장자 다른 애들은 len(fn)==1
        print('continue: ',fn)
        continue
    f_name_html=fn[0]+'.html'
    
    try:
        result = pdftotree.parse(f_name_pdf,html_path=None, model_type='table',model_path=None,visualize=False)
    except:
        print('continue')
        continue 
        
    with open('out.html','w',-1,'utf-8') as f:
        f.write(result)
    
    #전처리 코드
    import re
    file = open('out.html', 'r', encoding='utf-8')
    text = file.read()

    text = text.replace('\\n\\t', ' ')
    text = text.replace('\\t', '')

    text = text.replace('<table', '<table border=\'1\'')
	
    # f_name_html.html파일에 출력
    new_file = open(f_name_html, 'w', encoding='utf-8')
    new_file.write(text)
    new_file.close()

    file.close()

 

* 실행 전

이렇게 3개의 pdf가 있다.

 

* 실행 후

각각에 해당하는 html 파일들이 생성되었다.

 

 

※ 제 글이 도움이 되었다면 공감 부탁드려요 :)

반응형
Posted by mminky
파이썬2021. 6. 14. 09:54
728x90

[ 코드 ]

import re
# 패턴 넣으면 정규표현식 이용해서 해당하는 것 리스트로 리턴(find)
def match_dna_list(pattern_s, content_s):
    pattern_s_r = pattern_s.replace('_', '.')
    # pattern_s_r='(?=(.A....))'
    pattern_s_r = '(?=(' + pattern_s_r + '))'
    find = re.findall(pattern_s_r,content_s)

    #print(find)
    return find


with open ('3.inp','r') as f:
    #.strip()을 해줘야 \n 이 없어짐
    # \n 이 있으면 완전 다른 문자가 되기 때문에 findall()하면 안 나옴
    pattern = f.readline().strip()

    # 나머지부분 읽음
    dna_seq=''
    for i in f:
        dna_seq += i.strip()

    with open('dna.out', 'w') as f2:
        # find 안에 값이 있다면
        if ( match_dna_list(pattern,dna_seq) ):
            f2.write('\n'.join(match_dna_list(pattern,dna_seq)))
        else:
            f2.write('No')

 

 

[ 결과 ]

3.inp

_A____
CCCCCCCCCCCCCAAAATTTTTTTTGGGGGGGGGAAATTT

 

dna.out

 

----------------------------

 

* 정규표현식에서 모든 문자는 . 이다.

pattern_s_r = pattern_s.replace('_', '.')

 

* 겹치는 문자를 찾는 방법은 다음과 같다.

(?=( 패턴 )) 형식으로 만든 후 findall에 넣어준다.

pattern_s_r = '(?=(' + pattern_s_r + '))'
find = re.findall(pattern_s_r,content_s)

 

 

* 리스트로 return된 값을 '\n' 기준으로 출력하는 방법.

단, 마지막은 \n 없이 출력한다.

'\n'.join(출력원하는리스트)

print('\n'.join(match_dna_list(pattern,dna_seq)))

 

이때, 정수 리스트인 경우는 다음과 같이 map으로 str로 변경해준다.

list1=[1,2,3]
print('\n'.join(map(str,list1)))

 

 

반응형
Posted by mminky
파이썬2021. 6. 13. 20:46
728x90

* 문제

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

 

15973번: 두 박스

표준 입력으로 두 박스의 정보가 한 줄에 하나씩 주어진다. 각 박스의 정보는 왼쪽 아래 꼭짓점 좌표 (x1, y1)과 오른쪽 위 꼭짓점 좌표 (x2, y2)로 구성되는데 이들 좌푯값 x1, y1, x2, y2 (x1 < x2, y1 < y2)

www.acmicpc.net

 

[ 코드 ]

# box1의 a점(ax,ay), box1의 b점(bx,by)
ax,ay=0,0
bx,by=0,0
# box2의 c점, d점
cx,cy=0,0
dx,dy=0,0

def point(ax,ay,bx,by,cx,cy,dx,dy):
    if((ax,ay)==(dx,dy) or (bx,by)==(cx,cy) or (bx,ay)==(cx,dy) or (ax,by)==(dx,cy)) :
        return True

    else:
        return False

def line(ax,ay,bx,by,cx,cy,dx,dy):
    # 꼭짓점 하나 일치
    if(((bx,by)==(cx,dy) and by>cy) or (((bx,ay)==(cx,cy) and dy>ay))
    or((dx,cy)==(ax,ay) and by>cy) or ((dx,dy)==(ax,by) and dy>ay)
    # 변 일치
    or ((bx,by)==(cx,dy) and (bx,ay)==(cx,cy)) or ((ax,ay)==(dx,cy) and (dx,dy)==(ax,by))
    or ((cx, cy) == (ax, by) and (bx, by) == (dx, cy)) or ((ax, ay) == (cx, dy) and (dx, dy) == (bx, ay))
    # 그 사이(a,b의 한 변에 c,d가 겹침)
    or (ax==dx and (ay<cy<by or ay<dy<by)) or (bx==cx and (ay<cy<by or ay<dy<by))
    or (by==cy and (ax<cx<bx or ax<dx<bx)) or (ay==dy and (ax<cx<bx or ax<dx<bx))
    # 그 사이(c,d의 한 변에 a,b가 겹침)
    or (ax == dx and (cy < ay < dy or cy < by < dy)) or (bx == cx and (cy < ay < dy or cy < by < dy))
    or (by == cy and (cx < ax < dx or cx < bx < dx)) or (ay == dy and (cx < ax < dx or cx < bx < dx))
    # 내부 한 변 일치(ab안에 cd)
#    or (ay==cy and ax<cx<bx and ax<dx<bx and ay<dy<by) or (ax==cx and ay<cy<by and ay<dy<by and ax<dx<bx)
#    or (by==dy and ax<cx<bx and ax<dx<bx and ay<cy<by) or (bx==dx and ay<cy<by and ay<dy<by and ax<cx<bx)
    # 내부 한 변 일치(cd안에 ab)
#    or (ay==cy and cx<ax<dx and cx<bx<dx and cy<by<dy) or (ax==cx and cy<ay<dy and cy<by<dy and cx<bx<dx)
#    or (by==dy and cx<ax<dx and cx<bx<dx and cy<ay<dy) or (bx==dx and cy<ay<dy and cy<by<dy and cx<ax<dx)
    ):
        return True
    else:
        return False

def null(ax,ay,bx,by,cx,cy,dx,dy): #cy>by or ay>dy
    #dx<ax or bx<cx or min(cy,dy)>max(ay,by) or min(ay,by)>max(cy,dy)
    #우,좌,상,하 바깥에서 안 접할 때
    if(bx<cx or dx<ax or by<cy or dy<ay):
        return True
    #안에서 안 접할 때
    elif(bx-ax<dx-cx and by-ay<dy-cy and (cx<ax<dx and cx<bx<dx) and (cy<ay<dy and cy<by<dy)): #속에 들어감
        return True
    elif(bx-ax>dx-cx and by-ay>dy-cy and (ax<cx<bx and ax<dx<bx) and (ay<cy<by and ay<dy<by)): #속에 들어감
        return True
    else:
        return False


# main 함수
ax,ay,bx,by=map(int,input().split())
cx,cy,dx,dy=map(int,input().split())

if(line(ax,ay,bx,by,cx,cy,dx,dy)):
    print('LINE')
elif (point(ax,ay,bx,by,cx,cy,dx,dy)):
    print('POINT')
elif(null(ax,ay,bx,by,cx,cy,dx,dy)):
    print('NULL')
else:
    print('FACE')

 

[ 결과 ]

 

 


-----------------------------------------------------

case를 다 따져주는 것이 쉽지는 않은 것 같다.

아래의 그림을 보고 빠진 부분이 없는 지 확인해보면 좋을 것 같다 :)

 

* point

 

* line

아마 여기 코드 사진에 오타가 있을 것이다. 코드는 위에 첨부한 것을 참고하면 될 것 같다 :)

 

 

* null

 

 

 

※ 제 글이 도움이 되었다면 공감 부탁드려요 :)

반응형
Posted by mminky
파이썬2021. 6. 13. 20:07
728x90

[ 코드 ]

#(r,c)가 편해서 백준과 반대로 받음
#변수는 내 맘대로받는거니깐
r,c=map(int,input().split())
idx=int(input())

# 답 찾는 함수
def find_ans(p):
    if(p>r*c): #out of range
        print(0)
    for i in range(r):
        for j in range(c):
            if(arr[i][j]==p):
                print(i+1,j+1)

# 배정 된 표 만들기
arr=[[0 for _ in range(c)]for _ in range(r)]
x,y=0,-1
num=1 #넣을 번호
add=1 #1 or -1
for i in range(c,0,-1):
    j=i+(r-c-1)
    for _ in range(i):
        y+= add
        arr[x][y] = num
        num+=1
    for _ in range(j):
        x+=add
        arr[x][y]=num
        num+=1
    add*=-1 #방향 바꿈


find_ans(idx)

 

 

직접 표를 만들어서 찾는 방식으로 코딩했다.

85%까지는 느리게 느리게 채점이 되더니 결국 틀렸다고 한다..ㅠ

다음에 좀 더 보완해야겠다!

반응형
Posted by mminky
파이썬2021. 6. 13. 19:00
728x90

파이썬에서의 2차원 배열은 2차원 리스트이다.

근데 이게 col, row가 조금 헷갈려서 정리 해 둔다.

 

 

우선 5*3 리스트를 만든다.

 

arr = [[0 for _ in range(c)] for _ in range(r)]

  -> 이 코드를 통해 0으로 초기화 시킬 수 있다.

  [0을 c(=5)만큼 리스트로 만들고] 그거를 r(=3)만큼 리스트로 만들어라.

  이런 의미이다.

 

r,c  = 5,3
arr = [[0 for _ in range(c)] for _ in range(r)]
arr[2][0]=1
print(arr)

 

[ 결과 ]

 

----------------------------------

 

나는 다음과 같이 출력될 줄 알았다.

5*3 2차원 배열에서 (2,0)의 원소만 1로 변경 된 그림이다.

 

하지만 결과는 이렇게 출력되는 것 같다.

 

이거는 마치 다음의 그림처럼 세로로 읽은 결과로 보인다.

 

이러한 이유로 파이썬에서 2차원 배열을 만들 때는 주의를 기울여야 할 것 같다!

 

 

반응형

'파이썬' 카테고리의 다른 글

[ Python ] 백준 15973 (100점)  (0) 2021.06.13
[ Python ] 백준 10157 - 실패..  (0) 2021.06.13
[ Python ] 백준 11729 - 시간초과 해결!!  (0) 2021.06.06
[ Python ] 백준 13300 파이썬  (0) 2021.05.31
[ Python ] 백준 10828 파이썬  (0) 2021.05.31
Posted by mminky
파이썬2021. 6. 6. 19:28
728x90

* 문제
https://www.acmicpc.net/problem/11729

11729번: 하노이 탑 이동 순서

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로

www.acmicpc.net


[ 해결 원리 ]
하노이탑 개념에 대해 그림으로 쉽게 설명해두었으니 참고하면 좋을 것 같다 :)
https://mminky.tistory.com/116

[ C ] 분할정복 - 하노이탑 (a divide-and-conquer algorithm for the Towers of Hanoi problem)

[ 문제 ] Write a divide-and-conquer algorithm for the Towers of Hanoi problem. The Towers of Hanoi problem consists of three pegs and disks of different sizes. The object is to move the disks that a..

mminky.tistory.com



[ 코드 ]
**하노이탑 파이썬 - 시간초과가 떴다면**
print(count) 대신 print(2**n - 1) 를 해라!
-> 하노이탑의 총 옮긴 횟수는 2^n - 1으로 정해져 있다.
(하지만 개인적으로 옮길 때 마다 count를 증가시켜서 총 count를 출력하는 게 맞다고 생각한다.
근데 그렇게 하면 시간 초과가 된다..)

import sys input=sys.stdin.readline n = int(input()) #count = 0 #옮긴 횟수 #ans='' def hanoi(disk_num,from_peg,to_peg,tmp_peg): global count,ans if(disk_num==1): print(from_peg,to_peg) # ans += '{} {}\n'.format(from_peg,to_peg) # count += 1 return hanoi(disk_num-1,from_peg,tmp_peg,to_peg) print(from_peg,to_peg) # ans += '{} {}\n'.format(from_peg, to_peg) # count += 1 hanoi(disk_num-1,tmp_peg,to_peg,from_peg) print(2**n - 1) #count를 하니 시간 초과 뜸 # (처음)1 에서 (최종)3으로 이동함 # 2는 거치는 곳일 뿐! hanoi(n,'1','3','2') #print(count) #print(ans)



[ 결과 ]
와.. 진짜 시간초과 너무한거 아니냐고....
몇 번을 시도해서 결국 통과되었다.. 너무해..

반응형

'파이썬' 카테고리의 다른 글

[ Python ] 백준 10157 - 실패..  (0) 2021.06.13
[ Python ] 2차원 배열 (리스트)  (0) 2021.06.13
[ Python ] 백준 13300 파이썬  (0) 2021.05.31
[ Python ] 백준 10828 파이썬  (0) 2021.05.31
[ Python ] 백준 1735 파이썬  (0) 2021.05.31
Posted by mminky
파이썬2021. 5. 31. 00:37
728x90

[ 문제 ]

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

 

13300번: 방 배정

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에는 수학여행에 참가하는 학생 수를 나타내는 정수 N(1 ≤ N ≤ 1,000)과 한 방에 배정할 수 있는 최대 인원 수 K(1 < K ≤ 1,000)가 공백으로 분리되어

www.acmicpc.net

 

 

[ 코드 ]

 

#n: student num
#k : max people# in one room
n, k = map(int, input().split())
st = [[0]*2 for _ in range(6)] #성별2개 6학년

#입력
for _ in range(n):
    # st[학년][성별]
    s,y= map(int, input().split())
    st[y-1][s-1] += 1
#    print(st[y-1][s-1])

room_num=0
for a in range(6):#학년
    for b in range(2):#성별
        #print(st[a][b])
        #math.ceil써도 :)
        if(st[a][b]%k == 0):
            room_num += st[a][b]/k
        else:
            room_num += st[a][b]//k + 1
print(int(room_num))

 

 

[ 결과 ]

반응형
Posted by mminky
파이썬2021. 5. 31. 00:34
728x90

[ 문제 ]

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

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

 

[ 코드 ]

#시간초과 시 추가하면 좋은 구문
# https://www.acmicpc.net/board/view/44990
import sys
input=sys.stdin.readline

n = int(input()) #명령의 수
stack=[]

def push(x):
    #리스트의 마지막에 추가
    stack.append(x) #딱히 int(x)할 필요는 없을 듯

def pop():
    if(len(stack)==0):
        print(-1)
    else:
        print(stack.pop())

def size():
    print(len(stack))

def empty():
    if(len(stack)==0): #비면
        print(1)
    else: #안 비면
        print(0)

def top():
    if(len(stack)==0):
        print(-1)
    else:
        print(stack[-1])


for i in range(n):
    command=input().split() #push 1 같은 애들 분리
    if(command[0] == 'push'):
        push(command[1])
    if (command[0] == 'pop'):
        pop()
    if (command[0] == 'size'):
        size()
    if (command[0] == 'empty'):
        empty()
    if (command[0] == 'top'):
        top()

 

 

[ 결과 ]

반응형

'파이썬' 카테고리의 다른 글

[ Python ] 백준 11729 - 시간초과 해결!!  (0) 2021.06.06
[ Python ] 백준 13300 파이썬  (0) 2021.05.31
[ Python ] 백준 1735 파이썬  (0) 2021.05.31
[ Python ] 백준 1475 파이썬  (0) 2021.05.31
[ Python ] 백준 1453 파이썬  (0) 2021.05.31
Posted by mminky