6
\$\begingroup\$

Shorten (or not) text using run length encoding

Input:

heeeello
woooorld

Output:

1h4e2l1o
1w4o1r1l1d
  • Read lines from stdin.
  • Print to stdout.
  • Stderr is of course discarded.
  • Assume there are hidden testcases (no embedding of the output)
  • Input/Output as ASCII
  • Any language is accepted
\$\endgroup\$
  • 2
    \$\begingroup\$ You can (typically) save quite a bit if you ignore all ones, e.g. w4orld instead of 1w4o1r1l1d (you'd need to escape numerics, e.g. `f111 -> f3\1´). But then it would be a near-duplicate of this: codegolf.stackexchange.com/questions/6774 \$\endgroup\$ – primo Sep 14 '12 at 9:54
  • 1
    \$\begingroup\$ As it is it's close enough to Run-Length Encoding that I vote to close as dupe. It's not going to provide any new challenge or points of interest. \$\endgroup\$ – Peter Taylor Sep 14 '12 at 12:15
  • \$\begingroup\$ Bonus points for whoever manages to find a fixpoint. \$\endgroup\$ – FUZxxl Sep 15 '12 at 18:11
  • \$\begingroup\$ Run-Length Encoding may be the same at its core but the input format and the required output format are very different. \$\endgroup\$ – mroman Sep 15 '12 at 18:16
  • 1
    \$\begingroup\$ @FUZxxl, 22 is a trivial fixpoint. \$\endgroup\$ – Peter Taylor Sep 17 '12 at 18:15
2
\$\begingroup\$

Perl: 46 → 36 or 27 characters

perl -pe's|((.)\2*)|@x=split//,$1;@x.$x[0]|eg'

All hail @ardnew for coming up with the idea of using the tr///c operator to count the number of characters in the matched string instead of splitting:

perl -pe's|((.)\2*)|$1=~y///c.$2|eg'

Degolfed:

while(defined($_ = <>)) {
  $_ =~ s{((.)\2*)}           # match 1 or more consecutive identical non-newlines
         {
           ($1 =~ y///c )     # count the number of characters in $1
           .                  # and concatenate it
           $2                 # with the first matched character
         }eg;                 # execute substitution, match "global"
  print $_;                   # print the modified line
}

Usage:

$ perl -pe's|((.)\2*)|$1=~y///c.$2|eg' infile

or via STDIN

$ perl -pe's|((.)\2*)|$1=~y///c.$2|eg'
heeeello

prints

1h4e2l1o
\$\endgroup\$
  • \$\begingroup\$ You're short-changing yourself on your character count - I count 37 characters including 1 for the p option. \$\endgroup\$ – Gareth Sep 14 '12 at 22:30
  • \$\begingroup\$ You can save 10 chars by using s|((.)\2*)|$1=~y///c.$2|eg, which sums to 27 total chars (using the same character counting rules as @Gareth) \$\endgroup\$ – ardnew Sep 15 '12 at 3:29
1
\$\begingroup\$

J, 35 31 characters

,(](":@#,{.);.1~1,2~:/\])1!:1[1

Usage:

   ,(](":@#,{.);.1~1,2~:/\])1!:1[1
heeeello
1h4e2l1o
   ,(](":@#,{.);.1~1,2~:/\])1!:1[1
woooorld
1w4o1r1l1d
\$\endgroup\$
0
\$\begingroup\$

Bash: 104 characters

while read s;do e=;while [[ $s ]];do c=${s:0:1};n=${s##+($c)};e+=$[${#s}-${#n}]$c;s=$n;done;echo $e;done

Sample run:

bash-4.2$ while read s;do e=;while [[ $s ]];do c=${s:0:1};n=${s##+($c)};e+=$[${#s}-${#n}]$c;s=$n;done;echo $e;done <<END
heeeello
woooorld
END
1h4e2l1o
1w4o1r1l1d
\$\endgroup\$
0
\$\begingroup\$

Zsh, 117

while read s;do n=1;for i in {1..$#s};do if [[ $s[i] != $s[i+1] ]];then echo -n $n$s[i];n=0;fi;((n++));done;echo;done

Run it like this:

zsh script.zsh < infile

De-golfed

while read s; do                      # while stdin has more
  n=1                                 # repeat counter
  for i in {1..$#s}; do               # for each character
    if [[ $s[i] != $s[i+1] ]]; then   # same as next one?
      echo -n $n$s[i]                 # print if no
      n=0
    fi
    ((n++))
  done
  echo                                # newline between words
done
\$\endgroup\$
  • \$\begingroup\$ Are those white spaces necessary or can you shorten `if [' to 'if[' etc? \$\endgroup\$ – mroman Sep 14 '12 at 11:19
  • \$\begingroup\$ The [[ construct is a command on it's own (like [) and has to be separated from other commands. As to using [ over [[, it requires the arguments to be quoted so four " need to be added. \$\endgroup\$ – Thor Sep 14 '12 at 12:00
0
\$\begingroup\$

APL (24)

,↑{(⍕⍴⍵),⊃⍵}¨B⊂⍨B≠¯1⌽B←⍞
\$\endgroup\$
0
\$\begingroup\$

Burlesque (17B)

{=[{J[-jL[Q}\m}WL

{=[{^^[~\/L[Sh}\m}WL

Older/Alternative and longer versions:

{=[{^^L[Sh\/-]Sh.+}m[\[}WL
{=[{^^L[Sh\/-][-.+}m[\[}WL
{=[{^^L[Sh\/-~.+}m[\[}WL
{=[{^^L[Sh\/-].+}\m}WL
{=[{^^L[Sh\/[~.+}\m}WL
{=[{^^L[Sh\/[~_+}\m}WL
{=[{^^L[Sh\/fc.+}\m}WL
{=[{^^L[Sh\/-~.+}\m}WL
{=[{^^L[Sh\/-]\/}\m}WL
\$\endgroup\$
0
\$\begingroup\$

rs, 19 chars

This doesn't really count because I created rs way after this was posted...but it was fun anyway!

(.)(\1*)/(^^\1\2)\1

Try it here!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.