Bijection #짧은주소 를 만들어보자

bit.ly 를 보다보니

Short URL 서비스를 보다보니 다합쳐도 글자수로 22열 이다. (예: https://bit.ly/3o5QAs3) 문득 path 쪽을 유심히 보면 일정한 규칙에 의해서 작성이 되는듯하다

bit.ly 는 월에 2억개의 URL이 생성된다고 주장한다 Int(4byte) unsigned 기준으로 대략 42.8억의 표기를 한다 쳐도 10자리가 필요하다. 그것도 주장 대로라면 대략 21개월이면 꽉 채워 진다.

늘 그렇듯 검색의 바다에서 원리를 찾아 떠나다

이래저래 찾다보니 전단사 대응에 대해서 알게 되었다. 사실 우여 곡절이 많았다 BASE64 부터 md5, hex 등등 원하는 값이나 길이에 못미치는 상태 였다.

여윽시 chatGPT?

Bijection(전단사 대응)은 한 세트의 원소들을 다른 세트의 원소들로 일대일로 대응시키는 함수입니다. Python에서 bijection을 구현하는 방법은 여러 가지가 있지만, 가장 간단한 방법은 딕셔너리를 사용하는 것입니다. 딕셔너리는 각 원소를 키(key)와 값(value)으로 매핑하는 자료형입니다.

답은 쉽게 구할 수 있었지만 이 과정까지 가는데 검색 엔진을 이래저래 뒤지고 또 뒤지고 나서야 Bijection이라는 용어를 알게 되었다 사실 대략적으로 숫자의 값을 나눠서 나머지 (hex 와 비슷할꺼라 생각) 를 매칭할 계획이었다.

chatGPT 가 만들어준 코드

chatGPT는 개인적으로 중급 이상의 개발자에겐 정말 부사수 같은 개발자이지 싶다. 큰 그림을 그리다가 막상 코딩을 하려면 어디서 부터 할지 또는 중간 중간 검색을 통해서 그걸 검증하고 하는데 시간이 많이 걸리는데 chatGPT는 그런 부분에서 상당히 시간을 줄일 수 있도록 도와준다.

def create_bijection(keys, values):
    if len(keys) != len(values):
        raise ValueError("The number of keys and values must be the same.")

    bijection = {}
    for i in range(len(keys)):
        key = keys[i]
        value = values[i]
        if key in bijection:
            raise ValueError("Duplicate key found: " + str(key))
        if value in bijection.values():
            raise ValueError("Duplicate value found: " + str(value))
        bijection[key] = value

    return bijection

# 예시 사용법
keys = ['a', 'b', 'c']
values = [1, 2, 3]
bijection = create_bijection(keys, values)
print(bijection)  # 출력: {'a': 1, 'b': 2, 'c': 3}

# 특정 키에 대응하는 값을 얻을 수 있습니다.
print(bijection['a'])  # 출력: 1
print(bijection['b'])  # 출력: 2
print(bijection['c'])  # 출력: 3

옥헤이 좀더 디벨롭을 해보자

라고 외치지만 이미 누군가가 코딩을 잘 해둔게 있었다. 그냥 쓰자 ㅋ

해보니 뭔가 이상하다 무조건 가져다 쓰다가 낭패를 보았다.

class Dencoder():
    BASE64 = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/")
    SAFE_BASE64 = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
    URL_SAFE = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_;:.+=$")
    BASE62 = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
    HEX = list("0123456789ABCDEF")
    alphabet = BASE62

    def __init__(self, alphabet=None):
        if alphabet:
                self.alphabet = alphabet
        self.base = len(self.alphabet)

    def encode(self, number):
        if number == 0:
                return self.alphabet[0]
        s = ''
        while number > 0: 
                s += self.alphabet[number % self.base] # 이부분에 문제가 있다. (2023.07.20)
                number /= self.base
        return s[::-1] # reverse string

    def decode(self, s):
        i = 0
        for char in s:
                i = i * self.base + self.alphabet.index(char)
        return i

    def in_alphabet(self, s):
        for char in s:
                if char not in self.alphabet:
                        return False
        return True

다른건 문제 없었고 인코드 부분을 고쳐 보았다.


	
def encode(self, number):
  if number == 0:
    return self.alphabet[0]
  s = ''
  # 받아오는 number 가 0 에 대해서는 위에서 처리하니 넘어가자

  while number >= self.base: # 나누는 인수보다 작으면 루프가 돌지 않도록 구성
    remainder = number % self.base # 루프가 도는 동안 나머지에 대해서 Bijection 캐릭터에 매칭한다
    number = int(number // self.base) # 몫만 구한다 몫이 인수 보다 같거나 크면 계속 돌도록 한다
    s += self.alphabet[remainder] # String 에 매칭 되도록 한다.

  if number < self.base and number > 0 : # 최종 몫에 대해서 String 매칭을 한다.
    s += self.alphabet[number]

  return s[::-1] # reverse string

사용법

from dencoder import Dencoder

d = Dencoder()
print ( d.encode(234) )
print ( d.decode("xyz") )

일단 나의 경우에는 마리아DB 에서 프라이머리키 에서 사용을 해보려 한다 역수로 일일이 계산해서 넣을 계획은 아니고 어플리케이션에서 디코딩 후 역수처리를 할 계획이다.

댓글

이 블로그의 인기 게시물

북궐도 2.0

Python Strawberry GraphQL 예제 (feat. #sqlmodel, #mysql)

Arch 계열 리눅스 구글 크롬 설치