AttackOnNunu

Once more into the fray


  • 홈

  • About

  • 태그

  • 카테고리

  • 아카이브

  • 검색

(PYTHON) TextWrap

작성일 2020-02-20 In LANGUAGE 🚀 , PYTHON , TERMINOLOGY 댓글:

Reference

  • Python 공식 문서 - textwrap - Text wrapping and filling
  • ‘wrap’ 사전적 의미 - Cambridge Dictionary
  • ‘text wrap’의 뜻 - webopedia.com
  • ‘wrap text’의 뜻 - computerhope.com
  • ‘word wrap’의 뜻 - webopedia.com

(PYTHON) Day - 7 Strings에서 textwrap 패키지 를 사용하는 문제가 있었습니다. 뭔가 용어에 대해 정확히 이해하고 넘어가야 해당 기능이 필요할 때 기억해내고 사용할 것 같아서 아래에 정리해 두려고 합니다.

Wrap?

Image Search

Google에 ‘wrap’이라는 단어를 이미지로 검색해보면 왼쪽 사진과 같은 음식 사진들로 가득찬 것을 보실 수 있습니다.
한국어로 ‘랩’이라고 검색하면 오른쪽 사진과 같은 비닐랩 사진이 많이 보이지만 비교적 다양한 사진들이 섞여 있습니다.
많은 사람들이 wrap이라는 단어를 들었을 때 음식이나 주방요품을 떠올리면서 무언가를 감싸는 의미를 갖는 다는 느낌을 받습니다.

Cambridge Dictionary

[Verb]
to cover or surround something with paper, cloth, or other material
to cover someone with a piece of material in order to protect them

영어사전에서 찾아봐도 위에서 예상한 것 처럼 ‘무언가를 감싸는 것’을 뜻한다는 것을 볼 수 있습니다.
cover, surround 라는 단어에서 ‘덮는다’, ‘감싼다’라는 의미를 정확히 알 수 있는데, protect 라는 단어가 눈에 띄는군요.


Text Wrap?

‘text wrap’은 ‘plastic wrap’처럼 텍스트로 무언가를 감싸는 것을 뜻하는 것일까요?

Image Search

똑같이 Google 이미지 검색으로 ‘text wrap’을 찾아보면 위 사진처럼 특정 이미지에 맞춰 그 주위를 텍스트로 감싸는 것을 볼 수 있습니다. 이런 기능을 우리는 문서 작성 프로그램을 사용하며 자주 볼 수 있습니다. 한글로는 ‘텍스트 배치’라고 적혀있고 영어로 ‘text wrapping’이라고 적혀있는 것을 아래 사진을 통해 확인할 수 있습니다.

Webopedia

문득 Webo는 무엇을 뜻하는지 궁금해졌다. 백과사전을 뜻하는 Encyclopedia은 그리스어 Enkyklios Paideia(Complete Knowledge)에서 온 말이다. 이를 응용해서 Wikipedia는 wiki(인터넷 사용자 누구나 작성하고 수정할 수 있는) + pedia(지식)를 합친 뜻이 된다. 그렇다면 webo는 무슨 뜻이 있을까? 그냥 webpedia해도 되지않나? 왜 o가 들어갔지?

(본문의 내용을 요약한 것입니다. 정확한 내용은 위 출처를 통해 확인하실 수 있습니다.)

텍스트가 그래픽(이미지, 도표 등)을 감싸고 있는 것
HTML에서 <img> tag 안에 align=’left’ 혹은 ‘right’ 등을 선언함으로 텍스트 배치를 사용할 수 있다
동의어로 text flow 가 있다



하지만 문제에서 봤던 기능은 여기까지 알아본 내용과는 다른 것 같습니다. Python의 textwrap 패키지는 문단의 여백을 제어하는 기능인 것 같아서 조금 더 알아보겠습니다.

Wrap Text??

단어의 순서를 바꿔서 ‘wrap text’는 무언가로 텍스트를 감싸는 것을 뜻하는 것일까요?

Image Search

word, 한글과 같은 문서 작성 프로그램과는 다르게 Excel과 같은 spreadsheet 프로그램에서는 ‘wrap text’라는 기능을 제공합니다. 첫번째 사진에서 볼 수 있듯이 해당 기능은 텍스트를 셀 크기에 맞춰서 줄 바꿈을 실행합니다.

Webopedia

정해진 margin에 맞춰 강제로 텍스트의 형태를 바꾸는 것
동의어로 word wrap 이 있다

개인적으로 wraptext 혹은 wordwrap가 올바른 패키지 이름이지 않을까 하고 생각합니다. 왜 textwrap이 이름으로 채택되었는지 더 깊이 파고들지는 않겠습니다.



(PYTHON) Day - 7 Strings(3)

작성일 2020-02-18 In LANGUAGE 🚀 , PYTHON , HACKERRANK 댓글:

Reference

  • 문제 출처 - HackerRank
  • 파이썬 연습 - Practice - Python

개인적인 생각과 상상으로 작성한 내용들이 포함되어 있습니다
문제를 풀고 Discussion Tab을 참고하며 코드 스타일을 개선하려고 노력하고자 합니다



HackerRank

HackerRank의 Python 연습문제들은 아래와 같은 카테고리로 분류 된다:

Subdomain

  • Introduction
  • Basic Data Types
  • Strings
  • Sets
  • Math
  • Itertools
  • Collections
  • Date and Time
  • Errors and Exceptions
  • Classes
  • Built-Ins
  • Python Functionals
  • Regex and Parsing
  • XML
  • Closures and Decorators
  • Numpy
  • Debugging


Strings

Problem

  • Text Alignment
  • Text Wrap
  • Designer Door Mat
  • Alphabet Rangoli

기본 개념

Text Alignment

다음 함수를 사용하여 문자열은 좌, 우, 중앙으로 정렬시킬 수 있다
width는 필수로 입력해야하고 공백을 채울 문자(fillchar)는 선택적으로 입력, 기본값은 space
str.ljust(width[, fillchar]) : 왼쪽 정렬
str.center(width[, fillchar]) : 오른쪽 정렬
str.rjust(width[, fillchar]) : 가운데 정렬

  • INPUT
  • OUTPUT

5

    H    
   HHH   
  HHHHH  
 HHHHHHH
HHHHHHHHH
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHHHHHHHHHHHHHHHHHHHHHH   
  HHHHHHHHHHHHHHHHHHHHHHHHH   
  HHHHHHHHHHHHHHHHHHHHHHHHH   
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
  HHHHH               HHHHH             
                   HHHHHHHHH
                    HHHHHHH  
                     HHHHH   
                      HHH    
                       H  

Cone, Pillars, Belt 부분으로 나누어서 그림을 그려나가는 것이 흥미로웠다
아래 코드는 해당 문제를 풀때 Editor에 자동으로 입력되어 있던 코드에서 ljust, rjust, center 함수만 끼워 넣은 것이다

#Replace all **\_\_** with rjust, ljust or center.

thickness = int(input()) #This must be an odd number
c = 'H'

#Top Cone
for i in range(thickness):
print((c*i).rjust(thickness-1)+c+(c*i).ljust(thickness-1))

#Top Pillars
for i in range(thickness+1):
print((c*thickness).center(thickness*2)+(c*thickness).center(thickness*6))

#Middle Belt
for i in range((thickness+1)//2):
print((c*thickness*5).center(thickness\*6))

#Bottom Pillars
for i in range(thickness+1):
print((c*thickness).center(thickness*2)+(c*thickness).center(thickness*6))

#Bottom Cone
for i in range(thickness):
print(((c*(thickness-i-1)).rjust(thickness)+c+(c*(thickness-i-1)).ljust(thickness)).rjust(thickness\*6))
  • 재사용성을 생각했을 때, 각 부분들을 정의해 놓고 마지막에 출력할 때 필요한 부분들을 블럭을 조립하듯이 쌓으면 훨씬 깔끔한 것 같다
width =int(input())
c='H'

top_cone = [(c*(2*i+1)).center(2*width) for i in range(width)]
pillars = [(c*width + ' ' * 3 * width + c * width).center(6*width) for _ in range(width+1)]
base = [(c*5*width).center(6*width) for _ in range(width/2+1)]
bottom_cone = [r.rjust(6*width) for r in cone[::-1]]

print('\n'.join(top_cone + pillars + base + pillars + bottom_cone))

Text Wrap

문제 : 입력되는 문자열 S를 길이 w만큼 잘라서 출력
예제 : ‘ABCDEFGHIJKLIMNOQRSTUVWXYZ’를 4개씩 잘라서 ‘ABCD’, ‘EFGH’, … 로 출력

  • INPUT
  • OUTPUT

ABCDEFGHIJKLIMNOQRSTUVWXYZ
4

ABCD
EFGH
IJKL
IMNO
QRST
UVWX
YZ

import time
import textwrap

def wrap(string, max_width):
return '\n'.join([string[i:i+max_width] for i in range(0, len(string), max_width)])

def text_wrap(string, max_width):
return '\n'.join(textwrap.wrap(string, max_width))

if **name** == '**main**':
string, max_width = input(), int(input())

start_1 = time.time()
result = wrap(string, max_width)
end_1 = time.time()

start_2 = time.time()
result_2 = text_wrap(string, max_width)
end_2 = time.time()

print(result, result == result_2, sep='\n')
print('list_comprehension: '.ljust(20), round((end_1 - start_1) * 100, 8))
print('textwrap: '.ljust(20), round((end_2 - start_2) * 100, 8))
  • 7배 정도 느린데 굳이 textwrap 모듈을 사용해야 할까?

# input

ABCDEFGHIJKLIMNOQRSTUVWXYZ
4

# output

ABCD
EFGH
IJKL
IMNO
QRST
UVWX
YZ
True
list_comprehension: 0.00259876
textwrap: 0.01468658

Designer Door Mat

문제 : 예제와 같은 NxM 크기의 디자인 패턴을 그리는 문제(가운데 welcome, 패턴에는 -, |, . 세개만 사용, N은 홀수이고 M의 크기는 N의 3배)
예제 : 디자인 패턴 참고

  • INPUT
  • OUTPUT

9 27

  ------------.|.------------
  ---------.|..|..|.---------
  ------.|..|..|..|..|.------
  ---.|..|..|..|..|..|..|.---
  ----------WELCOME----------
  ---.|..|..|..|..|..|..|.---
  ------.|..|..|..|..|.------
  ---------.|..|..|.---------
  ------------.|.------------

위 Text Alignment 문제의 아이디어를 응용하여 패턴과 가운데 글자를 하나의 데이터로 정의하여 풀었음

if **name** == '**main**':
N, M = map(int, input().split())
pattern = [('.|.' * (2*i+1)).center(M, '-') for i in range(N//2)]
middle_pattern = 'WELCOME'.center(M, '-')

print('\n'.join(pattern), middle_pattern, '\n'.join(pattern[::-1]), sep='\n')

Alphabet Rangoli

문제 : Rangoli는 인도의 전통미술 패턴이다. 입력받는 N 크기의 랑골리 패턴을 그리는 문제
예제 : 랑골리 패턴 참고(크기가 커질수록 알파벳순으로 글자도 늘어남)

  • INPUT
  • OUTPUT

5

  --------e--------
  ------e-d-e------
  ----e-d-c-d-e----
  --e-d-c-b-c-d-e--
  e-d-c-b-a-b-c-d-e
  --e-d-c-b-c-d-e--
  ----e-d-c-d-e----
  ------e-d-e------
  --------e-------- 
import string

def print_rangoli(size):
alpha = string.ascii_lowercase
L = []
for i in range(n):
s = "-".join(alpha[i:n])
L.append((s[::-1]+s[1:]).center(4\*n-3, "-"))

print('\n'.join(L[:0:-1]+L))

if **name** == '**main**':
n = int(input())
print_rangoli(n)


(PYTHON) Day - 6 Strings(2)

작성일 2020-02-15 In LANGUAGE 🚀 , PYTHON , HACKERRANK 댓글:

Reference

  • 문제 출처 - HackerRank
  • 파이썬 연습 - Practice - Python

개인적인 생각과 상상으로 작성한 내용들이 포함되어 있습니다
문제를 풀고 Discussion Tab을 참고하며 코드 스타일을 개선하려고 노력하고자 합니다



HackerRank

HackerRank의 Python 연습문제들은 아래와 같은 카테고리로 분류 된다:

Subdomain

  • Introduction
  • Basic Data Types
  • Strings
  • Sets
  • Math
  • Itertools
  • Collections
  • Date and Time
  • Errors and Exceptions
  • Classes
  • Built-Ins
  • Python Functionals
  • Regex and Parsing
  • XML
  • Closures and Decorators
  • Numpy
  • Debugging


Strings

Problem

  • Mutations
  • Find a string
  • String Validators

기본 개념

Mutations

list형은 mutable하지만, tuple형은 immutable하다
immutable한 string 변수가 있을 때, 이를 수정하려면 어떻게 해야할까?
예제 : 5번째 위치의 ‘a’ 문자를 ‘k’로 바꿔라

  • INPUT
  • OUTPUT

abracadabra
5 k

abrackdabra

5가지 방법으로 문제를 해결해보고 각각의 시간을 측정해보았다
결과를 보면 ''.join() 함수만 사용한 방법이(아래 코드의 4번째 slice_join_2) 가장 수행속도가 빠르다

당연하지만 되도록이면 list(), format() 함수를 사용하거나, 반복문(list comprehension 안에 반복문을 사용)을 사용하지 않는 것이 5~10배 정도 수행시간을 단축시킬 수 있다

import time

def string_to_list(string, position, character):
string_li = list(string)
string_li[position] = character
string = ''.join(string_li)
return string

def string_format(string, position, character):
return ("{}{}{}".format(string[:position], character, string[position + 1:]))

def slice_join_1(string, position, character):
return string[:position] + character + string[position+1:]

def slice_join_2(string, position, character):
return character.join([string[:position], string[position+1:]])

def comprehension_1(string, position, character):
return ''.join([character if i == position else string[i] for i in range(len(string))])

def comprehension_2(string, position, character):
return ''.join([c if p != position else character for p, c in enumerate(string)])

if **name** == '**main**':
s = input()
i, c = input().split()
p = int(i)

start_1 = time.time()
s_1 = string_to_list(s, p, c)
end_1 = time.time()

start_2 = time.time()
s_2 = string_format(s, p, c)
end_2 = time.time()

start_3 = time.time()
s_3 = slice_join_1(s, p, c)
end_3 = time.time()

start_4 = time.time()
s_4 = slice_join_1(s, p, c)
end_4 = time.time()

start_5 = time.time()
s_5 = comprehension_1(s, p, c)
end_5 = time.time()

start_6 = time.time()
s_6 = comprehension_2(s, p, c)
end_6 = time.time()

print(s_1, s_1 == (s_2 and s_3 and s_4 and s_5 and s_6))

print('string_to_list: '.ljust(20), round((end_1 - start_1) * 100, 8))
print('string_format: '.ljust(20), round((end_2 - start_2) * 100, 8))
print('slice_join_1: '.ljust(20), round((end_3 - start_3) * 100, 8))
print('slice_join_2: '.ljust(20), round((end_4 - start_4) * 100, 8))
print('comprehension_1: '.ljust(20), round((end_5 - start_5) * 100, 8))
print('comprehension_2: '.ljust(20), round((end_6 - start_6) * 100, 8))
  • 수행시간이 워낙 빠르다보니 부동소수점 e로 표현이 되는데 한눈에 파악하기 어려워 임의로 100을 곱하고 반올림하였다
    (참고: e앞에 부분이 가수부, e뒤에 부분이 지수부이며 밑수는 10이라는 의미
    14e2는 14 x 10^2이므로 1400, 123e-3이라면 123 x 10^-3 = 123 x 0.001 = 0.123이다)
 # input
abracadabra
5 k

# output
abrackdabra True
string_to_list: 0.00178814
string_format: 0.00100136
slice_join_1: 0.00040531
slice_join_2: 0.0002861
comprehension_1: 0.00193119
comprehension_2: 0.00107288

Find a string

예제 : ABCDCDC에서 CDC가 몇 번 나타나는가

  • INPUT
  • OUTPUT

ABCDCDC
CDC

2

import time

def count_substring(string, sub_string):
cnt = 0
sub_len = len(sub_string)
loop_len = len(string) - sub_len + 1

for i in range(loop_len):
if string[i:i + sub_len] == sub_string:
cnt += 1

return cnt

def list_comprehension(string, sub_string):
return sum([1 for i in range(len(string) - len(sub_string) + 1) if string[i:i + len(sub_string)] == sub_string])


def list_comprehension_2(string, sub_string):
s_len = len(string)
sub_len = len(sub_string)
return sum([1 for i in range(s_len - sub_len + 1) if string[i:i + sub_len] == sub_string])

if __name__ == '__main__':
string = input().strip()
sub_string = input().strip()

start_1 = time.time()
count = count_substring(string, sub_string)
end_1 = time.time()

start_2 = time.time()
count_1 = list_comprehension(string, sub_string)
end_2 = time.time()

start_3 = time.time()
count_2 = list_comprehension_2(string, sub_string)
end_3 = time.time()

print(count, list(map(lambda x: x == count, [count_1, count_2])))
print('count_substring: '.ljust(20), round((end_1 - start_1) * 100, 8))
print('list_1: '.ljust(20), round((end_2 - start_2) * 100, 8))
print('list_2: '.ljust(20), round((end_3 - start_3) * 100, 8))
  • list comprehension을 사용하는 것이 아주 미세하게 빠르다
 # input
ABCDCDC
CDC

# output
2 [True, True]
count_substring: 0.00219345
list_1: 0.00197887
list_2: 0.00190735

String Validators

아래 함수들은 각각 문자열이 해당 범위에 속하는지 확인한다
str.isalnum() : alphanumeric(a-z, A-Z and 0-9)
str.isalpha() : alphabetical (a-z and A-Z)
str.isdigit() : 숫자 (0-9)
str.islower() : 소문자 (a-z)
str.isupper() : 대문자 (A-Z)

예제 : 입력되는 문자열이 alphanumeric, alphabetical, digits, lowercase와 uppercase를 가지는지 True/False로 출력

  • INPUT
  • OUTPUT

qA2

True
True
True
True
True

if **name** == '**main**':
s = input()

'''깔끔한 코딩
for method in [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]:
print any(method(c) for c in s)
'''

print(any(c.isalnum() for c in s))
print(any(c.isalpha() for c in s))
print(any(c.isdigit() for c in s))
print(any(c.islower() for c in s))
print(any(c.isupper() for c in s))


1…121314…33
NUNU

NUNU

개인적으로 공부하면서 정리한 내용들을 블로그에 남기고 있습니다.
99 포스트
18 카테고리
53 태그
RSS
Creative Commons
© 2021 NUNU
Powered by Hexo v3.9.0
|
Theme – NexT.Mist v7.2.0