Base85 인코딩


10

도전

ASCII 인쇄 가능 문자가 포함 된 단일 행 문자열을 입력하고 Base85로 인코딩 된 동일한 문자열 (빅 엔디안 규칙 사용)을 출력 할 수있는 프로그램을 작성하십시오 . 입력이 항상 ≤ 100 자라고 가정 할 수 있습니다.


Base85 가이드

  • 4 개의 옥텟은 (보통) 5 개의 Base85 문자로 인코딩됩니다.

  • Base85 문자의 범위 !u및 - (117 ASCII 33) z(ASCII 122).

  • 인코딩하려면 4 개의 8 진수 (32 비트 숫자)에서 85로 나누기를 계속 수행하고 나머지 (각 나누기 후)에 33을 더해 인코딩 된 값의 ASCII 문자를 가져옵니다. 예를 들어,이 프로세스의 첫 번째 응용 프로그램은 인코딩 된 블록에서 가장 오른쪽 문자를 생성합니다.

  • 4 개의 옥텟 세트에 널 바이트 만 포함 된 경우 z대신로 인코딩됩니다 !!!!!.

  • 마지막 블록이 4 옥텟보다 짧으면 널 바이트로 채워집니다. 인코딩 후에는 패딩으로 추가 된 동일한 수의 문자가 출력 끝에서 제거됩니다.

  • 인코딩 된 값 앞에 와가 와야 <~합니다 ~>.

  • 인코딩 된 값에는 공백이 없어야합니다 (이 문제의 경우).


In: easy
Out: <~ARTY*~>

In: test
Out: <~FCfN8~>

In: code golf
Out: <~@rGmh+D5V/Ac~>

In: Programming Puzzles
Out: <~:i^JeEa`g%Bl7Q+:j%)1Ch7Y~>

다음 스 니펫은 주어진 입력을 Base85로 인코딩합니다.


3
입력을 인쇄 가능한 ASCII로 제한하면 바이트8 진수 의 동의어로 사용하고 7 비트 바이트를 허용하지 않는 이유에 대해 혼란 스럽습니다 .
피터 테일러

엔디안을 지정해야합니다. 블록 [0,1,2,3]은 0x0123 또는 0x3210?
edc65

Wikipedia 링크에 따르면 @ edc65 빅 엔디 언
Level River St

3
@steveverrill 감사합니다. 그것은 외부 링크가 아니라 챌린지 텍스트에 있어야합니다. 적어도 그것은 지금 코멘트에있다
edc65

입력에 인쇄 가능한 문자 만 포함 할 수 있다면 어떻게 널 바이트를 포함 할 수 있습니까?
Luis Mendo

답변:


9

CJam, 43 39 35 바이트

"<~"q4/{:N4Ue]256b85b'!f+}/N,)<"~>"

CJam 통역사 에서 온라인으로 사용해보십시오 .

작동 원리

"<~"      e# Push that string.
q4/       e# Read all input from STDIN and split it into chunks of length 4.
{         e# For each chunk:
  :N      e#   Save it in N.
  4Ue]    e#   Right-pad it with 0's to a length of 4.
  256b85b e#   Convert from base 256 to base 85.
  '!f+    e#   Add '!' to each base-85 digit.
}/        e#
N,)       e# Push the length of the last unpadded chunk, plus 1.
<         e# Keep that many chars of the last encoded chunk.
"~>"      e# Push that string.

입력이 비어 있으면 N,)문자열에 적용됩니다 "<~". N처음에는 단일 문자를 보유 하므로 출력이 정확합니다.

입력에는 인쇄 가능한 ASCII 문자 만 포함되므로 z 를 처리 하거나 인코딩 된 청크를 길이 5로 채울 필요가 없습니다 .


3
이 솔루션은 ASCII 문자열의 Base85 버전과 유사하게 보입니다 (해당 마지막 예 참조). 잠깐만 ...
ojdo

1
@odjo : CJam 코드에 잘못된 문자가 있습니다. 가장 가까운 것은 CJam 인터프리터 링크입니다.
schnaader

@ojdo 도전은 이렇 기 때문에 :a program that can take an input of a single-line string containing any ASCII printable characters,...
edc65

5

파이썬 3, 71 바이트

from base64 import*
print(a85encode(input().encode(),adobe=1).decode())

필자는 파이썬에서 골프를 본 적이 없으므로 아마도 최적이 아닙니다.

3 바이트를 사용하지 않은 @ZachGates에 감사드립니다!


1
input().encode()대신 str.encode(input())3 바이트를 절약 할 수 있습니다 .
Zach Gates

@ZachGates 감사합니다! 모든 인코딩 / 디코딩은 여전히 ​​나를 죽이고 있습니다.
Dennis

2

파이썬 2, 193 162 바이트

from struct import*
i=raw_input()
k=4-len(i)%4&3
i+='\0'*k
o=''
while i:
 b,=unpack('>I',i[-4:]);i=i[:-4]
 while b:o+=chr(b%85+33);b/=85
print'<~%s~>'%o[k:][::-1]

이것은 나의 첫 번째 코드 골프이므로 내 접근 방식에 문제가 있다고 확신합니다. 또한 라이브러리 함수를 호출하는 대신 실제로 base85를 구현하고 싶었습니다. :)


181 바이트입니다. 저장할 때 IDLE이 코드에 추가하는 줄 바꿈을 제거하는 것을 잊지 마십시오 (IDLE을 사용하는 경우). 또한 함수를 호출하거나 사용자 입력을 얻지 않으므로 실행할 때 아무것도하지 않습니다.
Zach Gates

함수인지 I / O를 읽어야하는지 또는 stdin을 읽고 stdout을 인쇄해야하는지 확실하지 않습니까? (이전에 코드 골프를 한 번도 해 본 적이 없습니다 ...)
David

프로그래밍 퍼즐 및 코드 골프에 오신 것을 환영합니다! 4로 나눌 수없는 입력 길이에 문제가있는 것 같습니다 (마지막 2 개의 테스트 사례). 3 행을 읽어야 [:4+len(s)/4*4]하며 출력 끝에서 문자가 제거되지 않아야 합니다.
Dennis

문제를 해결했다고 생각합니다 (불행히도 더 길어졌습니다). 더 최적화하려고 노력하는 중
David

두 번째 while루프를 다음과 같이 바꿀 수 있습니다 : while b:d=chr(b%85+33)+d;b/=85. print명령문과 문자열 사이의 공백을 제거 할 수도 있습니다 . 또한에 전달 된 인수 사이의 공백을 제거하십시오 s.unpack.
Zach Gates

2

옥타브, 133131 바이트

stdin 대신 argv에서 입력을 받아 2 바이트를 절약 할 것을 제안 한 @ojdo에게 감사드립니다.

function g(s) p=mod(-numel(s),4);s(end+1:end+p)=0;disp(['<~' dec2base(swapbytes(typecast(s,'uint32')),'!':'u')'(:)'(1:end-p) '~>'])

언 골프 드 :

function g(s)             %// function header
p=mod(-numel(s),4);       %// number of missing chars until next multiple of 4
s(end+1:end+p)=0;         %// append p null characters to s
t=typecast(s,'uint32');   %// cast each 4 char block to uint32
u=swapbytes(t);           %// change endian-ness of uint32's
v=dec2base(u,'!':'u');    %// convert to base85
w=v'(:)'(1:end-p);        %// flatten and truncate resulting string
disp(['<~' w '~>']);      %// format and display final result

ideone에 코드를 게시했습니다 . 독립형 함수는 요구하고 end진술 하지 않지만 , ideone에는 동일한 파일에 함수와 호출 스크립트가 있으므로 구분 기호가 필요합니다.

나는 여전히 stdin아이디어 를 얻는 방법을 알 수 없었습니다. 아는 사람이 있다면 여전히 관심이 있으니 의견을 남겨주세요.

이데온의 샘플 출력 :

easy
<~ARTY*~>
test
<~FCfN8~>
code golf
<~@rGmh+D5V/Ac~>
Programming Puzzles
<~:i^JeEa`g%Bl7Q+:j%)1Ch7Y~>

왜 사용하지 argv()않습니까? 작업 설명은에서 입력을 읽을 필요가없는 것 같습니다 stdin.
ojdo

아주 좋아요! 그렇게 dec2base옥타브에서 36 위 기지 허용?
Luis Mendo

doc (및 오류 메시지)에서 말했듯이 argument BASE는 2에서 36 사이의 숫자 이거나 기호 문자열 이어야합니다 . 여기서 표현식 은 기본으로 사용되는 'i':'u'85 자 문자열 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu을 확장합니다 .
ojdo

@ojdo 만약 그렇다면, 함수로 만들고 몇 바이트를 저장해야합니다.
비커

1
@ 비커입니다. 36으로의 제한뿐만 아니라 숫자가 반드시 0 ... 9ABC라는 사실 때문에 ASCII 코드가 급격히 증가합니다.
Luis Mendo

1

Matlab, 175 바이트

s=input('','s');m=3-mod(numel(s)-1,4);s=reshape([s zeros(1,m)]',4,[])';t=char(mod(floor(bsxfun(@rdivide,s*256.^[3:-1:0]',85.^[4:-1:0])),85)+33)';t=t(:)';['<~' t(1:end-m) '~>']

예:

>> s=input('','s');m=3-mod(numel(s)-1,4);s=reshape([s zeros(1,m)]',4,[])';t=char(mod(floor(bsxfun(@rdivide,s*256.^[3:-1:0]',85.^[4:-1:0])),85)+33)';t=t(:)';['<~' t(1:end-m) '~>']
code golf
ans =
<~@rGmh+D5V/Ac~>

1

PHP, 181 바이트

foreach(str_split(bin2hex($argn),8)as$v){for($t="",$d=hexdec(str_pad($v,8,0));$d;$d=$d/85^0)$t=chr($d%85+33).$t;$r.=str_replace("!!!!!",z,substr($t,0,1+strlen($v)/2));}echo"<~$r~>";

온라인 버전

넓히는

foreach(str_split(bin2hex($argn),8)as$v){
    for($t="",$d=hexdec(str_pad($v,8,0));$d;$d=$d/85^0)
      $t=chr($d%85+33).$t;
    $r.=str_replace("!!!!!",z,substr($t,0,1+strlen($v)/2));
}
echo"<~$r~>";

1

순수 배쉬, ~ 738

인코더 우선 (골프) :

#!/bin/bash
# Ascii 85 encoder bash script
LANG=C

printf -v n \\%o {32..126};printf -v n "$n";printf -v m %-20sE abtnvfr;p=\<~;l()
{ q=$(($1<<24|$2<<16|$3<<8|$4));q="${n:1+(q/64#378iN)%85:1}${n:1+(q/614125)%85:1
}${n:1+(q/7225)%85:1}${n:1+(q/85)%85:1}${n:1+q%85:1}";};k() { ((${#p}>74))&&ech\
o "${p:0:75}" && p=${p:75};};while IFS= read -rd '' -n 1 q;do [ "$q" ]&&{ print\
f -v q "%q" "$q";case ${#q} in 1|2)q=${n%$q*};o+=($((${#q}+32)));;7)q=${q#*\'\\}
o+=($((8#${q%\'})));;5)q=${q#*\'\\};q=${m%${q%\'}*};o+=($((${#q}+07)));;esac;}||
o+=(0);((${#o[@]}>3))&&{ [ "${o[*]}" = "0 0 0 0" ]&& q=z|| l ${o[@]};p+="${q}";k
o=(); };done;[ "$o" ]&&{ f=0;for((;${#o[@]}<4;)){ o+=(0);((f++));};((f==0))&&[ \
"${o[*]}" = "0 0 0 0" ]&&q=z||l ${o[@]};p+="${q:0:5-f}";};p+="~>";k;[ "$p" ]&&e\
cho "$p"

테스트 :

for word in easy test code\ golf Programming\ Puzzles ;do
    printf "%-24s" "$word:"
    ./enc85.sh < <(printf "$word")
  done
easy:                   <~ARTY*~>
test:                   <~FCfN8~>
code golf:              <~@rGmh+D5V/Ac~>
Programming Puzzles:    <~:i^JeEa`g%Bl7Q+:j%)1Ch7Y~>

그리고 지금 디코더 :

#!/bin/bash
# Ascii 85 decoder bash script
LANG=C

printf -v n "\%o" {33..117};printf -v n "$n";o=1 k=1;j(){ read -r q||o=;[ "$q" \
]&&[ -z "${q//*<~*}" ]&&((k))&&k= q="${q#*<~}";m+="$q";m="${m%~>*}";};l(){ r=;f\
or((i=0;i<${#1};i++)){ s="${1:i:1}";case "$s" in "*"|\\|\?)s=\\${s};;esac;s="${\
n%${s}*}";((r+=${#s}*(85**(4-i))));};printf -v p "\%03o" $((r>>24)) $((r>>16&255
)) $((r>>8&255)) $((r&255));};for((;(o+${#m})>0;)){ [ "$m" ] || j;while [ "${m:0
:1}" = "z" ];do m=${m:1};printf "\0\0\0\0";done;if [ ${#m} -ge 5 ];then q="${m:0
:5}";m=${m:5};l "$q";printf "$p";elif ((o));then j;elif [ "${m##z*}" ];then pri\
ntf -v t %$((5-${#m}))s;l "$m${t// /u}";printf "${p:0:16-4*${#t}}";m=;fi;}

enc85.shdec85.sh,에 복사 chmod +x {enc,dec}85.sh한 다음 :

./enc85.sh <<<'Hello world!'
<~87cURD]j7BEbo80$3~>
./dec85.sh <<<'<~87cURD]j7BEbo80$3~>'
Hello world!

그러나 더 강력한 테스트를 수행 할 수 있습니다.

ls -ltr --color $HOME/* | gzip | ./enc85.sh | ./dec85.sh | gunzip

724 자로 줄어듦 :

printf -v n \\%o {32..126};printf -v n "$n";printf -v m %-20sE abtnvfr;p=\<~
l(){ q=$(($1<<24|$2<<16|$3<<8|$4))
q="${n:1+(q/64#378iN)%85:1}${n:1+(q/614125)%85:1}${n:1+(q/7225)%85:1}${n:1+(q/85)%85:1}${n:1+q%85:1}"
};k() { ((${#p}>74))&&echo "${p:0:75}" && p=${p:75};};while IFS= read -rd '' -n 1 q;do [ "$q" ]&&{
printf -v q "%q" "$q";case ${#q} in 1|2)q=${n%$q*};o+=($((${#q}+32)));;7)q=${q#*\'\\}
o+=($((8#${q%\'})));;5)q=${q#*\'\\};q=${m%${q%\'}*};o+=($((${#q}+07)));;esac;}||o+=(0)
((${#o[@]}>3))&&{ [ "${o[*]}" = "0 0 0 0" ]&&q=z||l ${o[@]};p+="${q}";k
o=();};done;[ "$o" ]&&{ f=0;for((;${#o[@]}<4;)){ o+=(0);((f++));}
((f==0))&&[ "${o[*]}" = "0 0 0 0" ]&&q=z||l ${o[@]};p+="${q:0:5-f}";};p+="~>";k;[ "$p" ]&&echo "$p"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.