Thực hiện bổ sung chuỗi đúng


29

Nhiều ngôn ngữ cho phép các chuỗi được "thêm" với +. Tuy nhiên, đây thực sự là một sự kết hợp, một sự bổ sung thực sự sẽ tuân theo các tiên đề của nhóm:

  • Nó được đóng lại (việc thêm hai chuỗi bất kỳ luôn luôn là một chuỗi)

  • Nó là liên kết ( (a + b) + c = a + (b + c) )

  • Có một danh tính ( e: a + e = a )

  • Mọi phần tử đều có nghịch đảo ( a: b: a + b = e )

(nối ghép vi phạm tiên đề nhóm 4)

Vì vậy, nhiệm vụ của tôi đối với bạn là thực hiện bổ sung chuỗi thực, đó là một hàm lấy hai chuỗi byte đại diện cho chuỗi và trả về một phần ba sao cho hàm của bạn thỏa mãn tất cả các tiên đề nhóm trên chuỗi byte.

Nó phải hoạt động trên tất cả các chuỗi byte đại diện cho các chuỗi bao gồm cả chuỗi có byte rỗng.

Đây là vì vậy câu trả lời sẽ được tính bằng byte với ít byte hơn.

Câu trả lời:


5

Python 3 , 177 170 163 130 byte

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

Hãy thử trực tuyến!

-14 byte nhờ notjagan

-33 byte nhờ Leaky Nun (và chuyển đổi endianness)

Tôi không có kinh doanh cố gắng chơi bất cứ thứ gì trong Python, nhưng tôi không muốn sử dụng Lua vì phương pháp này cần các số nguyên chính xác lớn để hoạt động trên các đoạn dài hợp lý. (Lưu ý: thuật toán vẫn thực sự chậm khi tăng độ dài chuỗi.) Điều này chủ yếu chỉ để cung cấp câu trả lời;)

Mỗi chuỗi là tự đảo ngược và chuỗi trống là danh tính. Điều này chỉ đơn giản là thực hiện xor dưới một mệnh đề đơn giản giữa các chuỗi và số nguyên không âm. slà một hàm trợ giúp tính toán mệnh đề (chỉ một chiều) và dlà nghịch đảo.

Phiên bản không chậm (148 byte, lịch sự của 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

Hãy thử trực tuyến!

Tôi cũng sẽ chiếm đoạt điều này cho một mồi theo lý thuyết nhóm.

Bất kỳ nghịch đảo đúng là một nghịch đảo trái: inv (a) + a = (inv (a) + a) + e = (inv (a) + a) + (inv (a) + inv (inv (a))) = inv (a) + (a + inv (a)) + inv (inv (a)) = (inv (a) + e) ​​+ inv (inv (a)) = inv (a) + inv (inv (a) ) = e

Điều này cũng có nghĩa là a là nghịch đảo của inv (a) .

Bất kỳ danh tính bên phải là một danh tính bên trái: e + a = (a + inv (a)) + a = a + (inv (a) + a) = a

Danh tính là duy nhất, được cung cấp danh tính khác f : e = e + f = f

Nếu a + x = a thì x = e : x = e + x = (inv (a) + a) + x = inv (a) + (a + x) = inv (a) + a = e

Nghịch đảo là duy nhất, nếu a + x = e thì: x = e + x = (inv (a) + a) + x = inv (a) + (a + x) = inv (a) + e = inv (a )

Việc làm theo các bằng chứng sẽ giúp việc xây dựng các mẫu đối với các giải pháp được đề xuất không thỏa mãn các đề xuất này trở nên khá dễ dàng.

Đây là một thuật toán tự nhiên hơn mà tôi đã thực hiện (nhưng không chơi gôn) ở Lua . Có lẽ nó sẽ cho ai đó một ý tưởng.

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

Ý tưởng về cơ bản là phân tách chuỗi dựa trên các thành phần sức mạnh của hai chiều dài của nó, và sau đó coi chúng là các trường có thành phần bị thiếu đại diện cho 0 và mỗi thành phần không bị thiếu biểu thị các số từ 1 đến 256 ^ n, vì vậy tổng 256 ^ n + 1 giá trị. Sau đó, các đại diện này có thể được thêm modulo khôn ngoan thành phần 256 ^ n + 1.

Lưu ý: Việc triển khai Lua này sẽ có các vấn đề tràn số đối với các chuỗi có kích thước lớn hơn 7. Nhưng bộ chuỗi có độ dài 7 trở xuống được đóng lại dưới phần bổ sung này.

Hãy thử trực tuyến!


Sự thật thú vị: Bởi vì mọi yếu tố là nghịch đảo của riêng nó, nhóm này cũng là abelian.
Phù thủy lúa mì

4

Thạch , 8 byte

‘ḅ⁹^/ḃ⁹’

Điều này sử dụng ánh xạ phỏng đoán φ từ mảng byte đến số nguyên không âm, XOR kết quả của việc áp dụng φ cho hai chuỗi đầu vào, sau đó áp dụng φ -1 cho kết quả.

Mảng trống là phần tử trung tính và mỗi mảng byte là nghịch đảo của chính nó.

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

‘ḅ⁹^/ḃ⁹’  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.

Tôi đã tự hỏi những esolang nào có nội dung chuyển đổi cơ sở sinh học ...
Neil

Có nên tấn công căn cứ đó không?
Tít

@Titus Không, các chữ số của song ánh căn cứ phạm vi 256 1-256 (bao gồm).
Dennis

Vậy ḅ⁹là từ cơ sở bijective 256 đến số nguyên? Không A+Acho cái gì? chr(-1)?
Tít

@Titus Quá trình chuyển đổi từ cơ sở sang số nguyên là giống hệt nhau cho các cơ sở tính toán và "bình thường". [65] + [65]sẽ mang lại [].
Dennis

3

Python 2 , 114 byte

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''

Hãy thử trực tuyến! Hoạt động bằng cách XOR các chuỗi được hiểu là cơ sở phỏng đoán 256 cuối nhỏ.


d=lambda s:s>''and-~ord(s[0])+d(s[1:])*256tiết kiệm ba byte; s=lambda d:d*'?'and chr(~-d%256)+s(~-d/256)tiết kiệm thêm một lần nữa
Lynn

@Lynn Có phải cái thứ hai sẽ làm việc cho d lớn không?
Neil

Làm thế nào điều này hoạt động nếu các chuỗi không có cùng độ dài?
Thuật sĩ lúa mì

@WheatWizard Độ dài của chuỗi không liên quan. Có một ánh xạ phỏng đoán từ tập hợp chuỗi đến tập hợp số nguyên. Các giá trị nguyên sau đó được XORed và ánh xạ đảo ngược.
Neil

@Neil Ok cảm ơn tôi thấy bây giờ.
Phù thủy lúa mì

1

Python 2 , 197 byte

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]

Hãy thử trực tuyến!

Biến chuỗi thành một số (giảm bằng mã số), phủ định nếu lẻ, sau đó giảm một nửa. Không phải là golf như người khác, nhưng nhanh hơn: P



1
nkhông phải là tiêm, gây ra vấn đề. Ví dụ n("\x00\x00")==n("\xff"), điều này không thành công:print(f("\x00\x00","") == "\x00\x00")
tehtmi

: | ồ không, điều đó sẽ rất tốn kém để sửa chữa
ASCII chỉ có

1 or=>1or
Zacharý
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.