92
\$\begingroup\$

Super simple challenge today, or is it?

I feel like we've heard a fair bit about double speak recently, well let's define it in a codable way...

Double speak is when each and every character in a string of text is immediately repeated. For example:

"DDoouubbllee  ssppeeaakk!!"

The Rules

  • Write code which accepts one argument, a string.
  • It will modify this string, duplicating every character.
  • Then it will return the double speak version of the string.
  • It's code golf, try to achieve this in the smallest number of bytes.
  • Please include a link to an online interpreter for your code.
  • Input strings will only contain characters in the printable ASCII range. Reference: http://www.asciitable.com/mobile/

Leaderboards

Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.

var QUESTION_ID=188988;
var OVERRIDE_USER=53748;
var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;function answersUrl(d){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+d+"&pagesize=100&order=asc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(d,e){return"https://api.stackexchange.com/2.2/answers/"+e.join(";")+"/comments?page="+d+"&pagesize=100&order=asc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){answers.push.apply(answers,d.items),answers_hash=[],answer_ids=[],d.items.forEach(function(e){e.comments=[];var f=+e.share_link.match(/\d+/);answer_ids.push(f),answers_hash[f]=e}),d.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){d.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),d.has_more?getComments():more_answers?getAnswers():process()}})}getAnswers();var SCORE_REG=function(){var d=String.raw`h\d`,e=String.raw`\-?\d+\.?\d*`,f=String.raw`[^\n<>]*`,g=String.raw`<s>${f}</s>|<strike>${f}</strike>|<del>${f}</del>`,h=String.raw`[^\n\d<>]*`,j=String.raw`<[^\n<>]+>`;return new RegExp(String.raw`<${d}>`+String.raw`\s*([^\n,]*[^\s,]),.*?`+String.raw`(${e})`+String.raw`(?=`+String.raw`${h}`+String.raw`(?:(?:${g}|${j})${h})*`+String.raw`</${d}>`+String.raw`)`)}(),OVERRIDE_REG=/^Override\s*header:\s*/i;function getAuthorName(d){return d.owner.display_name}function process(){var d=[];answers.forEach(function(n){var o=n.body;n.comments.forEach(function(q){OVERRIDE_REG.test(q.body)&&(o="<h1>"+q.body.replace(OVERRIDE_REG,"")+"</h1>")});var p=o.match(SCORE_REG);p&&d.push({user:getAuthorName(n),size:+p[2],language:p[1],link:n.share_link})}),d.sort(function(n,o){var p=n.size,q=o.size;return p-q});var e={},f=1,g=null,h=1;d.forEach(function(n){n.size!=g&&(h=f),g=n.size,++f;var o=jQuery("#answer-template").html();o=o.replace("{{PLACE}}",h+".").replace("{{NAME}}",n.user).replace("{{LANGUAGE}}",n.language).replace("{{SIZE}}",n.size).replace("{{LINK}}",n.link),o=jQuery(o),jQuery("#answers").append(o);var p=n.language;p=jQuery("<i>"+n.language+"</i>").text().toLowerCase(),e[p]=e[p]||{lang:n.language,user:n.user,size:n.size,link:n.link,uniq:p}});var j=[];for(var k in e)e.hasOwnProperty(k)&&j.push(e[k]);j.sort(function(n,o){return n.uniq>o.uniq?1:n.uniq<o.uniq?-1:0});for(var l=0;l<j.length;++l){var m=jQuery("#language-template").html(),k=j[l];m=m.replace("{{LANGUAGE}}",k.lang).replace("{{NAME}}",k.user).replace("{{SIZE}}",k.size).replace("{{LINK}}",k.link),m=jQuery(m),jQuery("#languages").append(m)}}
body{text-align:left!important}#answer-list{padding:10px;float:left}#language-list{padding:10px;float:left}table thead{font-weight:700}table td{padding:5px}
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/primary.css?v=f52df912b654"> <div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td><a href="{{LINK}}">{{SIZE}}</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td><a href="{{LINK}}">{{SIZE}}</a></td></tr></tbody> </table> 

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, [Other information] N bytes

where N is the size of your submission. Other information may include flags set and if you've improved your score (usually a struck out number like <s>M</s>). N should be the right-most number in this heading, and everything before the first , is the name of the language you've used. The language name and the word bytes may be links.

For example:

# [><>](http://esolangs.org/wiki/Fish), <s>162</s> 121 [bytes](https://esolangs.org/wiki/Fish#Instructions)
\$\endgroup\$
9
  • 5
    \$\begingroup\$ It will modify this string. Are you intentionally requiring pass-by-reference and modify in-place? And then return a copy or reference to that modified string? If so, languages like asm or C would need to accept an explicit-length string (pointer + length) where the length is either the current string length (with the buffer being twice that size), or it's the total size and you need to duplicate the low half. Thus you need to start from the end and work backwards, or allocate scratch space and then copy back. But there are answers in C and 8086 asm that totally violate all that. \$\endgroup\$ Aug 3, 2019 at 1:49
  • 5
    \$\begingroup\$ @PeterCordes I do not care if it modifies the same object or builds a new one. \$\endgroup\$
    – AJFaraday
    Aug 3, 2019 at 5:08
  • 4
    \$\begingroup\$ I'd suggest wording it as "modify (or produce a modified copy) of the string" to explicitly allow answers that do or don't modify in-place. Simplifying the wording to "return a string that's twice as long, with each character repeated" would be nice but then it's not clear if void foo(char *c, size_t len) is legal that takes one input/output buffer and a length, and doesn't have any return value, just a side-effect on the object it has a pointer to. \$\endgroup\$ Aug 3, 2019 at 5:16
  • 1
    \$\begingroup\$ @cschultz2048 it says the string will only contain printable ascii characters, so that implies that they’ll always be populated. I’d expect that any code for this challenge would leave an empty string empty... anyway, I don’t think it’s a test case that I’d use for this. \$\endgroup\$
    – AJFaraday
    Aug 6, 2019 at 22:36
  • \$\begingroup\$ Does this answer your question? Stretching Words Because when you make the two operands in any submission to that challenge equal, programs will obey the behavior described in this challenge. An example of this behavior is here. \$\endgroup\$
    – user85052
    Jan 2, 2020 at 12:29

239 Answers 239

1
4 5
6
7 8
2
\$\begingroup\$

Python 3, 31 bytes

for t in input():print(t,end=t)

a simple program of python

for t in input():

asking for the input, and doing a for loop for every char in the string.

print(t,end=t)

print the character, and then close the line with the same character.

\$\endgroup\$
1
2
\$\begingroup\$

R, 61 bytes

function(x){paste0(rep(strsplit(x,"")[[1]],e=2),collapse="")}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Bash, 45 bytes

while IFS= read -n1 c;do printf %s"$c$c";done 

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Yeah I removed this part. Btw. I'm not sure if it's a valid solution, because the string is not modified but a copy is printed. \$\endgroup\$
    – stephanmg
    Nov 11, 2019 at 11:45
  • \$\begingroup\$ @JoKing: You are probably right. \$\endgroup\$
    – stephanmg
    Nov 11, 2019 at 11:57
2
\$\begingroup\$

MIT-Scheme 10.*, 52 bytes

(lambda(x)(string-map(lambda(y)(make-string 2 y))x))

MIT-Scheme 10.* apparently has the new string-map which simplifies my earlier approach listed below. The only difference is that make-string is used to convert the character argument into a string and duplicate it.

74 bytes

This is the older solution for MIT-Scheme 9.* before string-map was introduced.

(lambda(x)(list->string(append-map(lambda(k)(list k k))(string->list x))))

This is an anonymous lambda that takes the input as a string, converts it to a list so that it can be mapped (I don't know of another way to do the same), replicating each character and joining it together in one list, after which it is converted back into a string.

\$\endgroup\$
2
\$\begingroup\$

GolfScript, 4 bytes

{.}%

Try it online!

Takes an input, which it treats as a list of characters, and maps . (push top item of stack to stack) over them.

\$\endgroup\$
2
\$\begingroup\$

Pip, 4 bytes

aWVa

Try it online!

The operator WV ("weave") takes two iterables and interleaves their elements. In this case, weaving the input string with itself produces the desired output.

\$\endgroup\$
2
\$\begingroup\$

W j, 5 2 bytes

+M

If you want to specify your input, you need to split your input into a list of individual characters before you do your job. (If that disobeys the rules, I will implement a flag that does this job for the writer. (Flags don't count in bytecount.))

Say your input is abcdef. Find imps.py and change those variables:

read = [["a","b","c","d","e","f"]]

prog = '+M'

Explanation

Lots of implicit stuff here. Expanded program:

aaa+M

The + requires 2 inputs and M only provides a single input. Therefore two 'a''s are prepended.

The M only has 1 input required left, so a single 'a' is prepended.
a     % The Implicit input
    M % Map every item of this input with...
 aa   % This every item with this every item...
   +  % Concatenated together

% Implicit Output
j % Join the output without a separator

Wren, 24 bytes

Fn.new{|s|s.map{|n|n+n}}

Try it online!

For every item in the list, return every item concatenated with itself.

\$\endgroup\$
2
\$\begingroup\$

Forth, (GForth) 55 bytes

: d pad 80 accept 0 do pad i + c@ dup emit emit loop ;

Usage: d [enter]

This text will be doubled. [enter]

Online Forth interpreter

'accept' takes a line of up to 80 chars into pad, then the do loop fetches chars from the pad, duplicates them and emits them to the terminal.

\$\endgroup\$
2
\$\begingroup\$

Rexx (Regina), 41 bytes

I just realized the rules specifically state "It will modify this string, duplicating every character." Since the newline is part of the string, I will now leave it in the string and duplicate it, thus reducing my code size to 42 bytes (according to ls -l, TIO says 41).

b=''
DO 80
a=CHARIN()
b=b||a||a
END
SAY b

Try it online!

Old 60 byte version which strips newlines (or CRs depending on your OS.)

b=''
DO 80
a=CHARIN()
b=b||a||a
END
SAY LEFT(b,LENGTH(b)-2)

Alternate last line (same number of bytes):

SAY STRIP(b,,X2C('0a'))

Do 80 iterations, read a char into var a, concatenate two a's onto the end of b during each loop, output the string minus the two newlines or CRs (need to modify for AmigaOS/AROS because it uses CR-LF for line terminators.)

62 byte original version:

DO 80
a=CHARIN()
x=CHAROUT(,a)CHAROUT(,a)
END

Read up to 80 chars from stdin into string var a, write 'a' to stdout twice for each char read in.

\$\endgroup\$
2
2
\$\begingroup\$

Elixir, 26 bytes

"#{for<<c<-s>>,do: [c,c]}"

Try it online!

\$\endgroup\$
2
\$\begingroup\$

PHP, 37 bytes

while($c=$s[$i++])$a.=$c.$c;return$a;

Try it online!

\$\endgroup\$
2
\$\begingroup\$

FEU, 12 bytes

s/(.)/\1\1/g

Try it online!

Just a single regex substitution.

\$\endgroup\$
2
\$\begingroup\$

Kite, 111 94 79 bytes

Really surprised that nobody has used Kite before on CGCC... it's a really easy to learn language.

method d(a)[(a|split("")<-method(a)[a+a;])<|method(a,b)[a|str*a|bool|int+b;];];

Test suite:

method d(a)[(a|split("")<-method(a)[a+a;])<|method(a,b)[a|str*a|bool|int+b;];];

(d("abc"))|print;

(d("Double speak"))|print;
\$\endgroup\$
2
\$\begingroup\$

Marbelous, 26 bytes

..@0
..00
..]]\/
../\
@0../\..

Marbelous is a language based on marble machines

  • @n (n from 0 to Z) is a portal which teleport the marble to another portal with the same value
  • 00-FF initiate a marble with this value
  • ]] read one byte of input into a parsing marble
  • \/ is a trash can
  • /\ create a duplicate passing marble to it's left and right
  • .. is a noop
  • marbles going out of the machine from the bottom are implicitly outputed

interpretor

\$\endgroup\$
2
\$\begingroup\$

Python 3, 67 64 bytes

t=input()
for i in map(lambda x:x[0]+x[1],zip(t,t)):print(end=i)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ print("".join(map("".join,zip(*[input()]*2)))) \$\endgroup\$
    – Danis
    Jan 25, 2021 at 19:00
  • \$\begingroup\$ j="".join;print(j(map(j,zip(*[input()]*2)))) \$\endgroup\$
    – Danis
    Jan 25, 2021 at 19:02
2
\$\begingroup\$

Whispers v1, 38 bytes

> Input
>> L+L
>> Each 2 1
>> Output 3

Try it online!

Squeezed pseudo code:

>> Output ( Input.map( c -> c + c ) )

Explanation:

As usual in Whispers, the last line is executed first by default:

>> Output 3

This line outputs the result of line 3:

>> Each 2 1

Here we expect line 2 to be a function and line 1 to be an array. It returns the array specified in line 1, whose elements were modified by the function in line 2. Let's look at this array first:

> Input

Takes the first line of the input. So we get an array of characters.

Now line 2:

>> L+L

L is an argument from the Each statement in line 3. Since we are working with strings, L is returned concatenated with itself.

So the squashed pseudo-code is:

>> Output ( Input.map( c -> c + c ) )
\$\endgroup\$
2
\$\begingroup\$

Haskell, 18 bytes

f s=s>>= \c->[c,c]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Factor + sequences.repeating, 12 bytes

[ 2 repeat ]

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Numberwang, 6 bytes

248337

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ That's Numberwang! \$\endgroup\$
    – Giuseppe
    Apr 16, 2021 at 14:18
  • 1
    \$\begingroup\$ Wang even is this language? \$\endgroup\$
    – AJFaraday
    Apr 16, 2021 at 14:33
2
\$\begingroup\$

[MashedPotatoes], 315 bytes

synchronized(0.0f){WHILEstd::ignore=`uniq-c`s/nullptr//gWENDgoto++i;(formatt"case__dict__of{_->OUTPUT=void(0)}def$ARGV(--help)usestrictqw/*read-eval*/;endgoto<>;gotoObject;defstd::ignore(--help)guardnullptrend(formatt"procFS{STDERR}{SETLOCAL()import$ARGV;}std::cout<<--help<<std::endl;goto0.0f;goto++i;")goto<>;")}

This is not short, by any means. But I've wanted to try and use MashedPotatoes for something, since the language is so odd. So it might be possible to shorten the code, but it's the sort of language where I'm relieved if I get something to work. :)

It's not available on TIO, so here's a link to the Esolang entry for the language. https://esolangs.org/wiki/MashedPotatoes There's a link the GitHub entry with the code on the page.

And there's one caveat about the interpreter... I submitted a PR to the repo to make it possible to handle EOF when reading character input, and this code relies on that enhancement. The maintainer merged it today (meaning 4/17/2021) so if you may need to refresh your copy if you pulled it previously.

I think a brief explanation of some language quirks are probably necessary first... There are 3 registers ^A, ^C, ^E, three stacks 0, 1, 2, two triggers A, B, and three labels 0, 1, 2 available.

The constants STDERR, $[, ~uniq -c~ (where I've used ~ to replace backticks since I cannot figure out how to make backticks work inside backticks) references registers ^A, ^C, ^E respectively the first time they appear in the code. Then they change to the next register the next time they are used. Meaning STDERR evaluates to the value of ^A the first time it appears in the code, to ^C the second time, etc...

Trigger A is referenced by the constants use strict qw/LABEL/;, SETLOCAL LABEL, import LABEL;, CFLAGS=LABEL, \emph{LABEL}, ~cat LABEL~ (again ~ used in place of a backtick here) cyclically. Meaning the first occurence of trigger A in the code will be use strict qw/LABEL/;, the second time will be SETLOCAL LABEL, etc... And LABEL is replaced the target label.

Similarly trigger ^B is references by the constants s/LABEL//g, OUTPUT = LABEL, guard LABEL, lambda: LABEL, """LABEL""", also in the same cyclical manner.

Label 0 is referenced by the symbols 0.0f, ++i, <>, Object cycically.

The cyclical reference names for label 1 are std::ignore, nullptr, __dict__, void(0).

And the label 2 references are $ARGV, *read-eval*, FS, ().

A better description can be found on the Esolangs page for the language.

And next, the code...

synchronized (0.0f) {

This just assign the label 0, the value 1 since the ( is on line 1 of the code.

  WHILE std::ignore = `uniq -c` s/nullptr//g WEND

Increments the value of register ^E.

  goto ++i;

Shifts the values of the registers, effectively ^A -> ^E -> ^C -> ^A

  (format t "

Loops while ^C is greater then 0

    case __dict__  of { _ -> OUTPUT = void(0) }

Reads one character from STDIN into ^A

    def $ARGV(--help) use strict qw/*read-eval*/; end

Pushes the value of ^A to stack 0, since ---help evaluates to 0

    goto <>;
    goto Object;

Shift the registers twice.

    def std::ignore(--help) guard nullptr end

Pop the value of stack 0 into ^A, the result of the the last 4 actions is effectively ^C = ^A

    (format t "

Loop as long as ^C > 0, effectively if not EOF { ... } since EOF is codepoint 0.

      proc FS {STDERR} {

Code block for output operations

        SETLOCAL ()

Print the value of ^A, mapping the codepoint to a character

        import $ARGV;

Repeats the same, meaning print ^A a second time

      }

End of output code block

      std::cout << --help << std::endl;

Set ^A to zero.

      goto 0.0f; 
      goto ++i;

Shift the registers twice, effectively sets ^C to 0 to cause the loop to exit

    ")

End of the print loop, which will never run more then once since we explicitly set ^C to 0 to prevent that.

    goto <>;

Shift the registers, sets ^C to the last codepoint read from STDIN, will be 0 on EOF.

  ")

End of the outermost (format loop, will decrement ^C and compare against 0, so if the read got any character the loop will repeat.

}

End of synchronize code block.

\$\endgroup\$
2
\$\begingroup\$

Hexagony, 11 bytes

,)</;(/@>;~

Try it online!

Just some simple control flow on this one, could def be improved.

\$\endgroup\$
2
\$\begingroup\$

MineFriff, 4 bytes

:oo~

Try it online!

No, I totally didn't forget to add input to MineFriff. You have to supply the string to double speak in the header, which can be generated using this Vyxal snippet.

Explained

:oo~
:    { duplicate the top of the stack }
 oo  { print it twice }
   ~ { back to the start of the line }
\$\endgroup\$
2
\$\begingroup\$

Zephyr, 89 bytes

input s
set i to 1
set o to""
while""<s[i...i]
set o to(o+s[i])+s[i]
inc i
repeat
print o

Try it online!

Explanation

Oh. My. Goodness.

I spent 20 minutes convinced this challenge wasn't possible in Zephyr. All the language design choices that I made 11 years ago came back to bite me:

  • There is no way to get the length of a string (not a design choice, I just didn't implement anything).
  • The print statement adds a trailing newline by default. Suppressing the trailing newline with ... adds a space instead.
  • The concatenation operator | also puts a space between the two values.

But a couple of things went right:

  • String slicing exists, and doesn't throw an error if the indices are out of bounds.
  • You can concatenate any value to a string using the + operator. In hindsight, I'm not sure why I thought this was a good feature, but there it is.

And so:

input string
set index to 1    # Zephyr uses 1-based indices
set output to ""
# Loop until index is out of bounds, at which point the string slice returns empty string
while "" < string[index...index]
    set output to (output + string[index]) + string[index]
    inc index
repeat
print output
\$\endgroup\$
2
\$\begingroup\$

Python, 67 bytes

from itertools import*
print(*chain(*[i*2for i in input()]),sep="")
\$\endgroup\$
2
\$\begingroup\$

Minim, 73 Bytes (44 w/o Output)

Program is run as follows:

C:\Users\chris> minim -a "Double speak!" -f golf.min

Arrays of values, and subsequently strings, cannot be returned or passed around to statements, and the interpreter uses only index 0 for a 'return/exit value'. Therefore I've opted to just print the modified string to the console.

[0]=L*2+1.[1:]=A.[[0]]=[[0]--/2]._^![0].C=1.[0]=2.$<[[0]++]._^![[0]].C=5.

With whitespace and comments:

;;; Insert string into memory and modify it

[0] = L * 2 + 1.         ; Set index 0 to twice the length of the program arguments plus 1
[1 :] = A.               ; Insert program arguments at index 1
    [[0]] = [[0]-- / 2]. ; Set index of index 0 to half of memory at index of index 0, and decrement index 0
    _^ ![0].             ; Skip the next statement if index 0 is 0
C = 1.                   ; Set program counter to 1

;;; Output modified string (no string/array return)

[0] = 2.        ; Set index 0 to 2.
    $< [[0]++]. ; Print index of index 0 as Unicode, and increment index 0
    _^ ![[0]].  ; Skip the next statement if index of index 0 is 0
C = 5.          ; Set program counter to 5

Without printing it, the program goes down to just 44 bytes.

[0]=L*2+1.[1:]=A.[[0]]=[[0]--/2]._^![0].C=1.

The modified string is now just in memory.

GitHub Repository

\$\endgroup\$
2
\$\begingroup\$

CLC-INTERCAL, 85 bytes.

DO;1<-#1DOCOMEFROM#2DOWRITEIN;1(1)DO:1<-;1SUB#1DDOCOMEFROM':1~:1'~#1(2)DOREADOUT;1+;1

Copy and paste to try it online!

With comments, though I don't know its necessity

DONOTE length of array
DO;1<-#1
DOCOMEFROM#2
DONOTE perform getchar() for a time to store to ;1SUB#1
DOWRITEIN;1
DONOTE EOF: zero; otherwise: at least 65536
(1)DO:1<-;1SUB#1
DONOTE die here
D
DONOTE ':1~:1'~#1: zero if EOF one otherwise
DOCOMEFROM':1~:1'~#1
DONOTE putchar() twice
(2)DOREADOUT;1+;1
\$\endgroup\$
2
\$\begingroup\$

Python 3, 31 24 bytes

-7 bytes by returning a list of characters instead of a string

lambda s:[c*2for c in s]

Returns a list of characters instead of a string.

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Mascarpone, 12 bytes

[,:..:!]v*:!

Try it online!

Pretty simple.

[      ]v*    Push the following as an operation to the stack.
 ,:..         Input a character and output it twice.
     :!   :!  Duplicate the operation and run it so that it loops.
\$\endgroup\$
2
\$\begingroup\$

dotcomma, 48 bytes

[[],][.[[[,],],]][.[,]][,[,[,.[[[,][,]][,.].]]]]

<script src="https://combinatronics.com/Radvylf/dotcomma/master/interpreter.js"></script><script src="https://code.jquery.com/jquery-3.5.1.min.js"></script><script>$(document).ready(function () {$("#btnInterpret").click(function () {$("#txtResult").text(interpret($("#txtCode").val(), $("#txtInput").val(), $("#lstOutputAs").children("option:selected").val()));});});</script><style>.textBox {background-color: white;border: 1px solid black;font-family: Courier New, Courier, monospace;width: 100%;}</style>Code: <textarea id="txtCode" type="text" class="textBox" style="height: 200px">[[],][.[[[,],],]][.[,]][,[,[,.[[[,][,]][,.].]]]]</textarea><br />Input: <textarea id="txtInput" type="text" class="textBox">Double speak!</textarea><br /><input id="btnInterpret" type="button" value="Run" />Output as: <select id="lstOutputAs"><option value="true">String</option><option value="">Number array</option></select><br />Result:<br /><div id="txtResult" class="textBox" style="overflow-wrap: break-word"></div>

Code:

[[],]                   insert end marker (0)
[.[                     while characters left
  [[,],],               copy each character 3 times
]]
[.[,]]                  go to first 0
[,[,[,                  delete copies of 0 and first character
  .[[[,][,]][,.].]      delete every third character until we reach 0 again
]]]
\$\endgroup\$
2
\$\begingroup\$

A0A0, 165 150 142 bytes

A0A0
A0C3G1G1A0
A0I1A6V0P0G6C6A0
A0A1G-3G-3A0
G-3

A0A0
C3G1G1A0C3G1G1A0

A0A1G-3G-3A0
G-3
A0A0
C3G1G1A0C3G1G1A0
G-10A0G-10A0
A0A1G-3G-3A0
G-3

The program consists of three loops right after one another. The first loop does the following:

I1A6V0P0G6C6
I1           ; take character input, store in V0
  A6         ; append this line to the line six below
    V0       ; operand, holds input
      P0     ; prints input
        G6   ; jumps to six lines below
          C6 ; removes all instructions on the six lines below

We duplicate the operand and print instructions a little lower, so we can print it twice. We then jump to there and the last C6 is to get rid of any other instructions that we didn't need afterwards.

The second loop is empty and is constructed from the first loop. The loop is also partially executed so we can enter the loop at the same place each time. This loop will print the character a second time. Because there is a nice G6 instruction inside the copied instructions that will also be executed, we use that as a way to escape from the infinite loop. This is because six lines below is yet another loop.

G-10G1G1
G-10     ; jumps 10 lines up, back to the first loop
    G1   ; no-op
      G1 ; no-op

This is a simple infinite loop (also partially executed) that takes us back to the first loop. It's padded with no-ops, since the loops needs at least three instructions. Because the first loop contains a C6, any redundant instructions in the second loop will be removed once we get back to the first loop.

Edit: Optimized by 15 bytes. I misunderstood the default loop template I make use of in the code. I was under the impression that the amount of G1 and G-3 instructions on line 2 and 4 of the loop resp. needed to match the amount of instructions inside the loop. This is not the case, you only need two of them (although more also work, as long as each line has an equal amount of them). This change removes these extra instructions.

Edit 2: Optimized by 8 bytes. Because of edit one, it turns out that there's actually no minimum of three instructions in the loop. This allows us to drop four instructions (not two, since the loop at the bottom is partially evaluated), totalling eight bytes.

\$\endgroup\$
1
4 5
6
7 8

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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