실제 문자열 추가 구현


29

많은 언어에서 문자열을로 추가 할 수 있습니다 +. 그러나 이것은 실제로 연결입니다. 진정한 추가는 그룹 공리를 따릅니다.

  • 닫힙니다 (두 개의 문자열을 추가하면 항상 문자열 임)

  • 연관성이 있습니다 ( (a + b) + c = a + (b + c) )

  • 정체성이 있습니다 ( ∃e : a + e = a )

  • 모든 요소에는 역수가 있습니다 ( ∀a : ∃b : a + b = e )

(연합은 네 번째 그룹 공리를 위반 함)

그래서 당신에게 내 임무는 진정한 문자열 추가를 구현하는 것입니다. 즉, 문자열을 나타내는 2 바이트 시퀀스를 취하고 함수가 바이트 시퀀스의 모든 그룹 공리를 만족하도록 1/3을 반환하는 함수입니다.

널 바이트가있는 문자열을 포함하여 문자열을 나타내는 모든 바이트 시퀀스에서 작동해야합니다.

이것은 이므로 바이트 수가 적을수록 답이 바이트로 표시됩니다.

답변:


5

파이썬 (3) , 177 (170) 163 130 바이트

lambda a,b:s(d(a)^d(b))
def s(n,x=0,s=''):
 while n:n-=1;s+=chr(n%256);n>>=8
 return s
def d(n,c=0):
 while s(c)!=n:c+=1
 return c

온라인으로 사용해보십시오!

notjagan 덕분에 -14 바이트

Leaky Nun (및 전환 엔디안) 덕분에 -33 바이트

파이썬에서 골프를 타려고하는 사업은 없지만이 방법에는 합리적인 길이의 찌르기를 작동시키기 위해 큰 정확한 정수가 필요하기 때문에 Lua를 사용하고 싶지 않았습니다. (참고 : 문자열 길이를 늘릴 때 알고리즘은 여전히 ​​매우 느립니다.) 대부분 대답을 제공하기위한 것입니다.

각 문자열은 자기 역수이며 빈 문자열은 ID입니다. 이것은 단순히 문자열과 음이 아닌 정수 사이의 간단한 bijection에서 xor를 수행합니다. s전단 사 함수를 (편도 만) 연산, 및 헬퍼 기능이다 d반전된다.

비 느린 버전 (148 바이트, Leaky Nun 제공) :

lambda a,b:s(d(a)^d(b))
def s(n,x=0,s=''):
 while n:n-=1;s=chr(n%256)+s;n>>=8
 return s
def d(n,c=0):
 while n:c=c*256+ord(n[0])+1;n=n[1:]
 return c

온라인으로 사용해보십시오!

나는 그룹 이론 입문서를 위해 이것을 납치 할 것입니다.

권리 역은 왼쪽 역 : (+ INV (INV (a)) INV (a)) = INV (a) + A = (INV (a) + A) + E = (INV (a) + A) + inv (a) + (a + inv (a)) + inv (inv (a)) = (inv (a) + e) ​​+ inv (inv (a)) = inv (a) + inv (inv (a) ) = 전자

이것은 또한 ainv (a)역함을 의미합니다 .

모든 오른쪽 항등은 왼쪽 항등입니다. e + a = (a + inv (a)) + a = a + (inv (a) + a) = a

다른 정체성 f가 주어지면 그 정체성은 유일하다 : e = e + f = f

만일 A + X = A 후, X = E : X = E + X = (INV (a) + A) + X = INV (a) + (A + X) = INV (a) + A = E

a + x = e 인 경우 역은 고유합니다 . . x = e + x = (inv (a) + a) + x = inv (a) + (a + x) = inv (a) + e = inv (a )

증거를 따르면 이러한 제안을 충족하지 않는 제안 된 솔루션에 대한 반례를 쉽게 구성 할 수 있어야합니다.

Lua 에서 구현 한 (그러나 골프는 아니었던)보다 자연스러운 알고리즘이 있습니다. 어쩌면 누군가에게 아이디어를 줄 것입니다.

function string_to_list(s)
  local list_val = {}
  local pow2 = 2 ^ (math.log(#s, 2) // 1) -- // 1 to round down
  local offset = 0
  list_val.p = pow2
  while pow2 > 0 do
    list_val[pow2] = 0
    if pow2 & #s ~= 0 then
      for k = 1, pow2 do
        list_val[pow2] = 256 * list_val[pow2] + s:byte(offset + k)
      end
      list_val[pow2] = list_val[pow2] + 1
      offset = offset + pow2
    end
    pow2 = pow2 // 2
  end
  return list_val
end

function list_to_string(list_val)
  local s = ""
  local pow2 = list_val.p
  while pow2 > 0 do
    if list_val[pow2] then
      local x = list_val[pow2] % (256 ^ pow2 + 1)
      if x ~= 0 then
        x = x - 1
        local part = ""
        for k = 1, pow2 do
          part = string.char(x % 256) .. part
          x = x // 256
        end
        s = s .. part
      end
    end
    pow2 = pow2 // 2
  end
  return s
end

function list_add(list_val1, list_val2)
  local result = {}
  local pow2 = math.max(list_val1.p, list_val2.p)
  result.p = pow2
  while pow2 > 0 do
    result[pow2] = (list_val1[pow2] or 0) + (list_val2[pow2] or 0)
    pow2 = pow2 // 2
  end
  return result
end

function string_add(s1, s2)
  return list_to_string(list_add(string_to_list(s1), string_to_list(s2)))
end

아이디어는 기본적으로 길이의 2의 제곱 구성 요소를 기준으로 문자열을 분할 한 다음 0을 나타내는 누락 구성 요소와 1에서 256 ^ n까지의 숫자를 나타내는 누락되지 않은 구성 요소가있는 필드로 처리하는 것입니다. 총 256 ^ n + 1 값입니다. 그런 다음 이러한 표현을 컴포넌트 단위 모듈로 256 ^ n + 1에 추가 할 수 있습니다.

참고 :이 Lua 구현에는 7보다 큰 크기의 문자열에 대해 숫자 오버 플로우 문제가 발생하지만 길이가 7 이하인 문자열 세트는이 추가에서 닫힙니다.

온라인으로 사용해보십시오!


재미있는 사실 : 모든 요소가 자신의 역수이기 때문에이 그룹도 아벨 리안입니다.
밀 마법사

4

젤리 , 8 바이트

‘ḅ⁹^/ḃ⁹’

이것은 바이트 배열에서 음이 아닌 정수 로 bijective mapping φ 를 사용하고 , XOR은 φ 를 두 입력 문자열 에 적용한 후 φ -1 을 적용합니다. 을 결과에 합니다.

빈 배열은 중립 요소이며 모든 바이트 배열은 자체 역수입니다.

온라인으로 사용해보십시오!

작동 원리

‘ḅ⁹^/ḃ⁹’  Main link. Argument: [A, B] (pair of byte arrays)

‘         Increment all integers in A and B.
 ḅ⁹       Convert from base 256 to integer.
   ^/     XOR the resulting integers.
     ḃ⁹   Convert from integer to bijective base 256.
       ’  Subtract 1.

나는 어떤 esolang이 bijective 기본 변환 내장을 가지고 있는지 궁금해하고 있었다.
Neil

기본 257이 아니어야합니까?
Titus

@Titus No, bijective base 256 의 자릿수는 1에서 256까지입니다 (포함).
Dennis

그래서 ḅ⁹으로부터 전단 사 기본 256 정수로? 무엇을 A+A제공합니까? chr(-1)?
Titus

@Titus 기본-정수 변환 프로세스는 bijective 및 "normal"기본에 대해 동일합니다. [65] + [65]생산할 것이다 [].
Dennis

3

파이썬 2 , 114 바이트

lambda a,b:s(d(a)^d(b))
d=lambda s:s and d(s[1:])*256+ord(s[0])+1or 0
s=lambda d:d and chr(~-d%256)+s(~-d/256)or''

온라인으로 사용해보십시오! little-endian bijective base 256으로 해석되는 문자열을 XORing하여 작동합니다.


d=lambda s:s>''and-~ord(s[0])+d(s[1:])*2563 바이트를 절약합니다. s=lambda d:d*'?'and chr(~-d%256)+s(~-d/256)하나 더 저장합니다.
Lynn

@Lynn 두 번째는 큰 d에서 작동합니까?
Neil

문자열의 길이가 같지 않으면 어떻게 작동합니까?
밀 마법사

@WheatWizard 줄의 길이는 관련이 없습니다. 문자열 집합에서 정수 집합으로의 형용사 매핑이 있습니다. 그런 다음 정수 값이 XOR되고 맵핑이 반대로됩니다.
Neil

@Neil Ok 감사합니다.
위트 마법사

1

파이썬 2 , 197 바이트

def n(s):
 n=s and ord(s[0])+1 or 0
 for c in s[1:]:n=n*256+ord(c)
 return(-1)**n*n/2
def f(l,r,s=""):
 i=n(l)+n(r)
 i=abs(i*2+(i<=0))
 while i>257:s=chr(i%256)+s;i/=256
 return["",chr(i-1)+s][i>0]

온라인으로 사용해보십시오!

문자열을 숫자로 바꾸고 (문자 코드로 줄임) 홀수이면 무시하고 반으로합니다. 다른 것만 큼 골프는 아니지만 더 빠릅니다 : P



1
n주사하지 않아 문제가 발생합니다. 예를 들면 n("\x00\x00")==n("\xff")다음과 같습니다.print(f("\x00\x00","") == "\x00\x00")
tehtmi

: | 아뇨, 그건 고칠 것
ASCII-only

1 or=>1or
Zacharý
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.