11
\$\begingroup\$

You have to write a function/program that takes input via the stdin/command-line arguments/function arguments, mixes up characters in a string, and then output the final string via the stdout.

Input will first contain a string (not empty or null), a space, and then an even number of non-negative numbers all separated by spaces. If input is taken via function arguments, the string will be the one of the arguments while the integers, which are seperated by a space, will be the other. You must swap the characters of the string at the indices corresponding to consecutive pairs of numbers.

For instance:

Hello_world! 0 6

must result in

wello_Horld!

Assumptions

  • You may choose between 0-based and 1-based indexing, and may assume that the given indexes will always be in range.
  • The string will not be longer than 100 characters and will only contain ASCII characters in range ! to ~ (character codes 0x21 to 0x7E, inclusive). See ASCII table for reference.
  • The two indices in a pair may be identical (in which case, nothing is swapped in that step).

Scoring

This is code golf, so the shortest submission (in bytes) wins.

Test Cases

Hello_world! 0 6 => wello_Horld!
First 1 2 1 0 0 4 => tFisr
(Second!$$) 8 7 10 1 => ()econd$!$S
~Third~ 0 0 6 6 0 6 6 0 => ~Third~
\$\endgroup\$
7
  • 2
    \$\begingroup\$ For future challenges, let me recommend the sandbox where you can get feedback and polish your challenge before posting it on main (this minimises the risk of invalidating existing answers if someone discovers a serious flaw in your challenge that needs fixing). \$\endgroup\$ Commented May 16, 2015 at 12:30
  • \$\begingroup\$ Why require input on stdin, and not, e.g., as command line arguments? \$\endgroup\$
    – lrn
    Commented May 16, 2015 at 14:26
  • \$\begingroup\$ @lrn , Right. Added 2 more options. \$\endgroup\$
    – Spikatrix
    Commented May 16, 2015 at 15:00
  • \$\begingroup\$ I see a bunch of solutions below that assume that they can get the list of indices as an array that gets passed into the function they implement. The way I read your definition, the input is a single string, which contains the indices as well as the string they operate on, and extracting the indices from the input string is part of the code that needs to be golfed. Can you clarify which interpretation is correct? \$\endgroup\$ Commented May 18, 2015 at 4:39
  • \$\begingroup\$ @RetoKoradi , No. Input is not a full string. It has a string, and then numbers. The numbers are not included in the string. \$\endgroup\$
    – Spikatrix
    Commented May 18, 2015 at 6:48

13 Answers 13

7
\$\begingroup\$

Python 3, 89 86 bytes

[*s],*L=input().split()
while L:a,b,*L=map(int,L);s[a],s[b]=s[b],s[a]
print(*s,sep="")

Unpack all the things. (3 bytes saved thanks to @potato)

\$\endgroup\$
2
  • \$\begingroup\$ Save a few bytes and do this: [*s],*L=input().split() you can then take the line after it away. I really like your solution btw, it's almost elegant even though it is very golfed. \$\endgroup\$
    – potato
    Commented May 17, 2015 at 18:40
  • \$\begingroup\$ @potato Oh wow, I didn't know you could have two unpacks together like that (I thought you could only do that in 3.5). Thanks! \$\endgroup\$
    – Sp3000
    Commented May 18, 2015 at 4:04
6
\$\begingroup\$

CJam, 11 bytes

rr{irie\r}h

How it works

This is a slightly different approach, in which I simply run a do-while loop till I have pairs of numbers left in the input.

r                 e# Read the first string
 r                e# Read the first number of the first number pair in the input
  {      }h       e# Do a do-while loop
   i              e# Convert the first number from the pair to integer
    ri            e# Read the second number from the pair and convert to intger
      e\          e# String X Y e\ works by swapping the Xth index with the Yth index in the
                  e# String
        r         e# This is our exit condition of the do-while loop. If we still have
                  e# a number on the input left, that means there are more pairs to swap.
                  e# Otherwise, we exit the loop and the result is printed automatically

Try it online here

\$\endgroup\$
4
\$\begingroup\$

CJam, 13 bytes

r[q~]2/{~e\}/

Test it here.

Explanation

r             e# Read the first token, i.e. the string.
 [q~]         e# Read the rest of the input, eval it and wrap it in an array.
     2/       e# Split the array into pairs of consecutive elements.
       {   }/ e# For each pair.
        ~     e# Unwrap the array.
         e\   e# Swap the corresponding elements in the string.
\$\endgroup\$
1
  • \$\begingroup\$ Whoa. Did not expect an answer that fast! \$\endgroup\$
    – Spikatrix
    Commented May 16, 2015 at 12:06
3
\$\begingroup\$

C (137 b)

f(char*T,int*V,int L){int C=0;for(int j=0;j<strlen(T);C=++j){for(int i=L-1;i+1;i--)if(C==V[i]){C=V[i-i%2*2+1];i-=i%2;}printf("%c",T[C]);}}

Explanation is coming ...

Arguments

T = a word of type char*.

V = an array of an even number of integer elements.

L = length of V

Output

mixed string

How does it work ?:

sweeps numbers of array V vice versa , and puts the nth element of the string after tracking all its progress until the actual point . Example

input= T="First" , V={1,2,1,0,0,4}

V inversed={4,0,0,1,2,1}

V[0] = 4th element -> index 0
0 -> 1
1->2

4th element 't' receives the second = 'r'

V[1] = 0 -> index 4
4 isnt mentionned after so , no changes

0 element='F' receives the fourth= 't'

V[3] = 1st element -> index 0
no changes

V[4] = 2 -> index 1
no changes after ..

Try it here

\$\endgroup\$
1
  • 1
    \$\begingroup\$ @Agawa001 , You can golf this a lot more. Return type int is not needed(may result in unexpected behavior), and int variables which are parameters do not need an int, variables, instead of declaring in the loop can be declared in one place outside the loop, use putchar instead of printf etc \$\endgroup\$
    – Spikatrix
    Commented May 17, 2015 at 5:15
3
\$\begingroup\$

Python 3 - 161 149

import sys
t=sys.stdin.read().split()
q=list(t[0])
c=1
i=int
while c<len(t):n=q;a=i(t[c]);b=i(t[c+1]);n[a]=q[b];n[b]=q[a];q=n;c+=2;
print(''.join(q))

Golfed more by swapping around some variables, and using ; as in Tim's comment.

I expected it to come out looking golfed, just not this much.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ You can golf this a lot. Change the while to while c<len(t):line1;line2;line3.... c=c+2 goes to c+=2 \$\endgroup\$
    – Tim
    Commented May 16, 2015 at 14:11
  • \$\begingroup\$ @Tim Thanks for your help! \$\endgroup\$ Commented May 16, 2015 at 14:58
  • \$\begingroup\$ Shouldn't c start at 0? \$\endgroup\$
    – Tim
    Commented May 16, 2015 at 14:59
  • \$\begingroup\$ @Tim Nope. c actually is indexing t (the input) to get the positions we need to swap. But since t[0] is the string we need to swap around, t[1] and t[2] hold the first pair of swaps. \$\endgroup\$ Commented May 16, 2015 at 15:01
  • \$\begingroup\$ Ahh I see, yes. Sorry, my solution split off the input, so i guessed you'd done the same :) \$\endgroup\$
    – Tim
    Commented May 16, 2015 at 15:09
3
\$\begingroup\$

C, 109 107 102 bytes

i;f(l){l=sizeof(a)/sizeof(*a);char t;for(;i<l;i+=2){t=s[a[i]];s[a[i]]=s[a[i+1]];s[a[i+1]]=t;}puts(s);}

Note: s and a needs to be declared as global arrays. s is the string which you want to swap and a is an array of int with all the number values.

If the above code does not work, try using void f(){...} instead of f(){...}

Ungolfed code:

int a[]={1, 2, 1, 0, 0, 4};//Integer elements
char s[]="First";          //String to be swapped

i; //Auto initialized to 0 and defaults to type int
void f(l){ //Variables defaults to type int
  l=sizeof(a)/sizeof(*a); //Gets number of elements in array a
  char t;

  for(;i<l;i+=2){ 

    t=s[a[i]];
    s[a[i]]=s[a[i+1]];
    s[a[i+1]]=t;  //Swap each character

  }

  puts(s); //Print the final char array
}

Test it here

\$\endgroup\$
4
  • \$\begingroup\$ hmm ur code is smaller :) \$\endgroup\$
    – Abr001am
    Commented May 16, 2015 at 15:31
  • \$\begingroup\$ lol where is variable declaration ? thats a cheaty way to tighten ur code :p \$\endgroup\$
    – Abr001am
    Commented May 16, 2015 at 15:54
  • \$\begingroup\$ @Agawa001 , I didn't include the variable declaration as the bytes would vary with each test case. \$\endgroup\$
    – Spikatrix
    Commented May 17, 2015 at 5:06
  • \$\begingroup\$ This does not match the input as defined in the problem. The input is a single string. Unless I completely misunderstood the problem, you need to extract the index values from the input string. \$\endgroup\$ Commented May 18, 2015 at 4:35
2
\$\begingroup\$

C, 70 bytes

Given that the input string is at most length 100 I decided to make the 'NULL' byte indicating the end of the integer array be the unambiguous 0xFF. Presumably this doesn't count as extra input, though for a cost of (at most) 7 3 bytes it can be made into 1-based indexing and use '\0' as the end of the array.

f(s,i,t)char*s,*i;{for(;~*i;)t=s[*i],s[*i]=s[*++i],s[*i++]=t;puts(s);}

Pretty much just does regular swapping with a tmp variable and uses that the comma operator introduces sequence points to have defined behaviour (unlike some manifestations of xor swaps that would have a lower character count but lead to undefined behaviour).

Edit: As requested you can test it out: http://rextester.com/OVOQ23313.

\$\endgroup\$
1
  • \$\begingroup\$ I don't think you can assume that you get an array with the indices to be swapped. The indices are part of the input string, and you need to parse them out of the string as part of the posted (and counted) code. From the description: "Input will first contain a string, a space, and then an even number of non-negative numbers all separated by spaces." \$\endgroup\$ Commented May 18, 2015 at 4:27
2
\$\begingroup\$

Dart - 123

Assumes input on the command-line is automatically split at spaces. Otherwise it needs an initial x=x[0].split(' '); to split the string into text and indices.

main(x,{c,i:1,a,t}){c=x[0].split("");n()=>a=int.parse(x[i++]);for(;i<x.length;t=c[n()],c[a]=c[n()],c[a]=t);print(c.join());}

With more whitespace:

main(x,{c,i:1,a,t}){
  c=x[0].split("");
  n()=>a=int.parse(x[i++]);
  for(;i<x.length;t=c[n()],c[a]=c[n()],c[a]=t);
  print(c.join());
}

Run/test this on dartpad.dartlang.org.

\$\endgroup\$
2
  • \$\begingroup\$ Do you know of any online compilers where I could test this? \$\endgroup\$
    – Spikatrix
    Commented May 17, 2015 at 5:12
  • \$\begingroup\$ Add link to DartPad. \$\endgroup\$
    – lrn
    Commented May 17, 2015 at 12:32
2
\$\begingroup\$

Rebol - 71

s: take i: split input" "foreach[a b]i[swap at s do a at s do b]print s

Ungolfed:

s: take i: split input " " 
foreach [a b] i [swap at s do a at s do b]
print s
\$\endgroup\$
3
  • \$\begingroup\$ How do I test this? Is there any online compiler for testing this? \$\endgroup\$
    – Spikatrix
    Commented May 17, 2015 at 12:43
  • \$\begingroup\$ @CoolGuy - Yes you can test it at try.rebol.nl The input function won't be able to call STDIN from there. The workaround is to simple set input to be the value you wish to test. Here's full example of the first test - input: "hello_World 1 7" s: take i: split input" "foreach[a b]i[swap at s do a at s do b]print s and click on Do in Rebol 3 NB. Rebol uses 1-based indexing. \$\endgroup\$
    – draegtun
    Commented May 17, 2015 at 12:48
  • \$\begingroup\$ @CoolGuy - Alternatively you can download Rebol 3 binaries from rebolsource.net \$\endgroup\$
    – draegtun
    Commented May 17, 2015 at 12:51
1
\$\begingroup\$

Python 3, 135

x=input().split()
y=list(x[0])
z=[int(i)for i in x[1:]]
while z:p,c=y[z[0]],y[z[1]];y[z[0]],y[z[1]]=c,p;del z[0],z[0]
print(''.join(y))

Explanation:

x=input().split()         # Split the input into a list at each space
y=list(x[0])              # First item in list (the word) into a list of chars
z=[int(i)for i in x[1:]]  # Make the list of numbers, into integers
while z:                  # Loop untill the list z is empty
    p,c=y[z[0]],y[z[1]]   # Assign p to the first char and c to the second
    y[z[0]],y[z[1]]=c,p   # Swap around using p and c
    del z[0],z[0]         # Remove the first 2 items in the list of integers
print(''.join(y))         # Print out the altered list as a string
\$\endgroup\$
1
\$\begingroup\$

C, 143 bytes

main(a,v,i)char** v;{i=2;char s[101],t;strcpy(s,v[1]);for(;i<a;i+=2){t=s[atoi(v[i])];s[atoi(v[i])]=s[atoi(v[i+1])];s[atoi(v[i+1])]=t;}puts(s);}

The above program takes input from command-line arguments, copies the string into an array, swaps corresponding characters and then, outputs the modified string.

Ungolfed code:

main(int a,char** v,int i){ //Arguments of main 
  i = 2;
  char s[101],t;

  strcpy(s,v[1]); //Copy string literal into an array

  for(;i<a;i+=2){
    t=s[atoi(v[i])];
    s[atoi(v[i])]=s[atoi(v[i+1])];
    s[atoi(v[i+1])]=t;  //Swap each character
  }

  puts(s); // Output the final string
}
\$\endgroup\$
2
  • \$\begingroup\$ Are you assuming that the numbers have only one digit? Considering that the input can be up to 100 characters, I don't think that will be valid. Also look at the 3rd example, which has 10 as one of the indices. \$\endgroup\$ Commented May 18, 2015 at 4:32
  • \$\begingroup\$ @RetoKoradi , Thanks for spotting that. I fixed the code. \$\endgroup\$
    – Spikatrix
    Commented May 18, 2015 at 6:06
1
\$\begingroup\$

JavaScript (ES6), 95

95 bytes with a single string input (function f below)

75 bytes with 2 parameters, string and number array (function g below)

(EcmaScript 6, Firefox only)

f=i=>
(
  n=i.split(' '),
  s=[...n.shift()],
  n.map((v,i)=>i&1?[s[v],s[w]]=[s[w],s[v]]:w=v),
  s.join('')
)

g=(s,n)=>
  n.map((v,i)=>i&1?[s[v],s[w]]=[s[w],s[v]]:w=v,s=[...s])
  &&s.join('')

// TEST
out=x=>O.innerHTML+=x+'\n'

;[['Hello_world! 0 6', 'wello_Horld!']
,['First 1 2 1 0 0 4','tFisr']
,['(Second!$$) 8 7 10 1','()econd$!$S']
,['~Third~ 0 0 6 6 0 6 6 0','~Third~']]
.forEach(t=>{
  u=f(t[0]),
  ok=u==t[1],
  out('Test '+(ok?'OK: ':'FAIL: ')+t[0]+'\n Result:' +u + '\n Check: '+t[1]+'\n')
})
<pre id=O></pre>

\$\endgroup\$
0
\$\begingroup\$

Vyxal, 11 bytes

$⌈⌊2ẇ(n~İṘȦ

Try it Online!

7 bytes by taking the string and then a list of lists of the indices to swap

Explained

$⌈⌊2ẇ(n~İṘȦ
$⌈           # Push the numbers split on spaces then the string.
  ⌊2ẇ        # eval each number in the rest and wrap into lists of size 2
     (       # to each pair:
      n~İ    #   without popping anything, index the pair into the string
         Ṙ   #   reverse that
          Ȧ  #   assign back to the string, vectorises
\$\endgroup\$

Your Answer

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

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