Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

You are given a string and two characters. You have to print the string between these characters from the string.

Input

Input will first contain a string (not empty or null). In the next line, there will be two characters separated by a space.

Challenge

Return the string between the two characters

Example

Hello! What's your name?
! ?

should result in the output:

" What's your name"

Rules

  • The string will not be longer than 100 characters and will only contain ASCII characters in range (space) to ~(tilde) (character codes 0x20 to 0x7E, inclusive). See ASCII table for reference.
  • You must take input from the stdin( or closest alternative ).
  • The output should be surrounded with quotes(").
  • You can write a full program, or a function which takes input, and outputs the final string
  • The two characters will only contain ASCII characters in range (space) to ~(tilde) (character codes 0x20 to 0x7E, inclusive). See ASCII table for reference.
  • There is no guarantee that both the characters will be in the string.
  • If any of the characters is not found in the string, print "null".
  • If any of the characters is found more than one times (unless both the characters are same) in a string, print "null".
  • If both the characters are the same character, print the string "null".

Test Cases

1)

<HTML>code</HTML>
> <                       --> "null"

2)

What's what?
' '                       --> "null"

3)

abcdefghijklmnopqrstuvwxyz
n k                       --> "lm"

4)

Testing...
e T                       --> ""

5)

Last test-case
  -                       --> "test"

Scoring

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

share|improve this question
3  
Can the characters occur in the opposite order in the string? If so, that could use a test case. –  Martin Büttner May 18 at 12:45
1  
What if the substring contains a "? Should we just surround it with another pair of quotes and not care about that? –  user23013 May 18 at 12:48
    
@MartinBüttner , Yes. See edited test case 3. Thanks for reminding me about that –  Cool Guy May 18 at 12:56
    
@user23013 , Yes. Example input: one"two-three \n" - output: "two" (\n is a newline) –  Cool Guy May 18 at 12:57
    
What I meant was input one"two-three \nn -. So the output should be "e"two"? –  user23013 May 18 at 13:01

12 Answers 12

up vote 3 down vote accepted

CJam, 34 33 32 bytes

'"l_l2%&2*2>NerN/0"null"t_,3=='"

Try it online in the CJam interpreter.

Idea

  1. Remove the second character from line 2.

  2. Form a string consisting of a single copy of all characters that both lines have in common.

  3. Repeat the resulting string twice and discard its first two characters.

    This results in a two-character string (if the characters from line 2 are different and both occur in line 1) or an empty string.

  4. Replace the characters of the resulting string in line 1 by linefeeds.

  5. Split line 1 at linefeeds.

    The resulting array's second element will be the desired string if the array contains exactly three chunks.

  6. Replace the first element of the array with the string null.

  7. Retrieve the second element of the array if its length is 3 and the first otherwise.

  8. Prepend and append a double quote.

Code

'"       e# Push a double quote.
l_       e# Read one line from STDIN. Push a copy.
l2%      e# Read one line from STDIN. Only keep characters at odd indexes.
&        e# Intersect both strings.
2*2>     e# Repeat the intersection twice and discard the first two characters.
Ner      e# Replace the characters of the resulting string with linefeeds.
N/       e# Split the result at linefeeds.
0"null"t e# Replace the first element of the resulting array with "null".
_,3=     e# Push 1 if the length of the array is 3 and 0 otherwise.
=        e# Retrieve the corresponding element from the array.
'"       e# Push a double quote.
share|improve this answer

CJam, 38 bytes

l:Tl2%f#_W-$2,=2,@f#$~T<>1>"null"?'"_o

Too long...

Explanation

l:T             e# Read a line and store in T.
l2%             e# Read the two characters into a list.
f#              e# Find each character in the list of two characters.
_W-             e# Copy and remove not found results.
$2,=            e# Sort and check if the result is exactly [0 1].
                e# If true:
2,@f#           e# Find 0 and 1 in the original results.
$               e# Sort.
~T<>            e# Get a slice of T between the two positions (left-closed).
1>              e# Remove the first character.
                e# If false:
"null"          e# The string "null".
?               e# End if.
'"_o            e# Append a quote and output another quote at the beginning.
share|improve this answer

Pyth, 37 36 34 bytes

p?"null"njT9m/zd{J%2wt:z.uSmxzdJNN

Thanks to @isaacg for the two bytes save.

Try it online: Pyth Compiler/Executor

Explanation:

                                     implicit: z = first input line
                    w                second input line
                  %2                 only use every 2nd char
                 J                   and store in J
                {J                   set(J), gets rid of duplicates
            m/zd                     count the number of appearances of each char
        njT1                         != [1, 1] ([1,1] is 10 in base 9)
 ?      njT1m/zd{J%2w                ... if [1,1] != number of appearances else ...
  "null"                               string "null"
                           mxzdJ     find the index for each char
                          S          sort the indices
                      :z.u           take the substring of z using these indices
                     t               remove the first char

p                               NN  print '"' + ... + '"'
share|improve this answer
    
*2]1 is shorter than [1 1), and - ... 1 is shorter still. –  isaacg 2 days ago
    
@isaacg -...1 don't work, since I also need to check that there are exactly two numbers. –  Jakube 2 days ago
2  
I just thought of a 3 character way to make [1 1): jT9. –  isaacg 2 days ago

Python 3, 149 bytes

s,i=input(),input();a,b=s.find(i[0]),s.find(i[2]);print('"'+('null',[s[a+1:b],s[b+1:a]][b<a])[(s.count(i[0])==s.count(i[2])==1)*(a!=b)*(a*b>-1)]+'"')

Ungolfed Version:

string, chars = input(), input()
a, b = string.find(chars[0]), string.find(chars[2])

    if string.count(chars[0]) == string.count(chars[2]) == 1 and a!=b and a*b>-1:
        if b<a:
            print('"' + string[b+1:a] + '"')
        else:
            print('"' + string[a+1:b] + '"')
else:
    print('"null"')

This is my first answer here, so tips and criticism are much appreciated.

share|improve this answer

Ruby, 108 95 94

->s,f,l{a,b=[f,l].map{|u|(f==l||s.count(u)>1)&&abort('"null"');s.index u}.minmax;p s[a+1...b]}

And for the ungolfed version

def between(string, first, last)
    left, right = [first, last].map do |substring|
        abort('"null"') if first == last || string.count(substring) != 1
        string.index(substring)
    end.minmax
    p string[left + 1 ... right]
end
share|improve this answer
    
Why can't I see any output when I run your code here? –  Cool Guy yesterday
    
@CoolGuy It is an unnamed function, so you need to call it like this ->s,f,l{begin a,b=[f,l].map{|u|raise if f==l||s.count(u)>1;s.index u}.minmax;p s[a+1...b];rescue;p'null'end}["<html>test</html>",?>,?<] The [...] at the end is what calls the function. –  blutorange yesterday
    
@blutorange , Ok. That sort-of worked, but how do I test the last test case? –  Cool Guy yesterday
    
@CoolGuy Use normally quoted strings: ->s,f,l{begin a,b=[f,l].map{|u|raise if f==l||s.count(u)>1;s.index u}.minmax;p s[a+1...b];rescue;p'null'end}["Last test-case"," ","-"] –  blutorange yesterday
    
Instead of raising an error with raise, you can replace raise with an undefined variable such as _ or y. This raises a NameError. Also, I think you could save a few more bytes without an explicit rescue: ->s,f,l{a,b=[f,l].map{|u|(f==l||s.count(u)!=1)&&p('null')&&exit;s.index u}.minmax;p s[a+1...b]} –  blutorange yesterday

C, 192 bytes

f(){char b[101],c,d,*p,*t;scanf("%[^\n]%*c%c%*c%c",b,&c,&d);p=strchr(b,c);t=strchr(b,d);c==d||!p||!t||strchr(p+1,c)||strchr(t+1,d)?puts("\"null\""):printf("\"%s\"",p<t?(*t=0,p+1):(*p=0,t+1));}

Ungolfed code:

f()
{
    char b[101],c,d,*p,*t; //Variables

    scanf("%[^\n]%*c%c%*c%c",b,&c,&d); //Scan input

    p=strchr(b,c);
    t=strchr(b,d); //Find occurrence of characters

    c==d         ||  //If both characters are the same
    !p           ||  //If no occurrence of first character found
    !t           ||  //If no occurrence of second character found
    strchr(p+1,c)||  //If two occurrence of first character found
    strchr(t+1,d) ?  //If two occurrence of second character found
    puts("\"null\"") //Print "null"
                  :  //else
    printf("\"%s\"",p<t?(*t=0,p+1):(*p=0,t+1)); //print the string
}

Test it here

share|improve this answer

Python 3, 172 bytes

x=input()
a=input()
a,b=a[0],a[2]
if(a!=b)&(x.count(b)==x.count(a)==1):
 if x.index(a)>x.index(b):q=a;a=b;b=q
 print('"'+x.split(a)[1].split(b)[0]+'"')
else:print('"null"')
share|improve this answer

Javascript (ES6), 125 123 bytes

Idea stolen heavily from @edc65's solution.

[a,,b]=(p=prompt)(s=p()),[,c,d,e,,f]=s.split(RegExp('(['+(a+b).replace(/\W/g,'\\$&')+'])'))
p('"'+(!e||f||c==e?null:d)+'"')

share|improve this answer
    
I mostly like [a,,b]=, I'll use it next time. As regexs are a hassle, here is a regex free solution: [a,,b]=(P=prompt)(s=P()), P((s=s.split(a)).length==2& (s=[].concat(...s.map(s=>s.split(b)))).length==3 ?``"${s[1]}"``:null) –  edc65 2 days ago
    
(the last string is templated, difficult to put in a comment) –  edc65 2 days ago

Python, 161 bytes

import re,sys
s,p=sys.stdin
m=re.match('[^%s]*([%s])([^%s]*)([%s])[^%s]*$'%((p[0]+p[2],)*5),s)
if m:g=m.group
print'"null"'if not m or g(1)==g(3)else'"'+g(2)+'"'

The solution mostly just uses a regular expression to extract the string. To accommodate that the letters could match in either direction, the start and end of the matched part allows either letter. Checking that the letters that actually matched to be different excludes the same letter being matched twice, as well as the two letters in the input being the same.

This is my first attempt at using Python for an answer here. So feedback on possible improvements is very welcome. I particularly have a feeling that there must be a way to make the condition in the print statement shorter.

share|improve this answer

Python 3, 155 bytes

s,n,a,b=[input(),'null']+list(input())[::2];q,w=[s.find(a),s.find(b)];print('"'+{0>1:n,0<1:s[min(q,w)+1:max(q,w)],a==b:n}[s.count(a)==s.count(b)==1]+'"')

Try it online

share|improve this answer

golflua, 132 bytes

L=I.r()I,J=I.r():m("(.) (.)")i=L:f(I)j=L:f(J)K,c=L:g(I,'')_,b=K:g(J,'')?i>j i,j=j,i$w((i==j|c+b!=2)&'"null"'|'"'..L:s(i+1,j-1)..'"')

Pretty ugly answer. The input bit is a bit rough (and requires two lines, first with the string & second with the slice characters ). Finding the locations of the flags is straight-forward, but just too long to compete with other answers. Output is pretty easy. An equivalent Lua program would be

Line1 = io.read()
Line2 = io.read()
I,J = Line2:match("(.) (.)")     -- boobs return the char flags
i = Line1:find(I)                -- find location of flags
j = Line1:find(J)
K,c = Line1:gsub(I,'')           -- replace flag w/ empty & store in K
_,b = K:gsub(J,'')               -- taking K ensures single flags fail
if i > j then i,j=j,i end        -- ensure we start low to high
if i==j or not (c+b == 2) then   -- if i & j are the same or not 2 counts, fail
   print('"null"')
else                             -- print the string otherwise
   print('"'..Line1:sub(i+1,j-1)..'"')
end
share|improve this answer
    
Is there any online compiler which I can test the golfed version? –  Cool Guy 20 hours ago
    
I don't believe there's an online version, but the source code is available. It is a 1:1 mapping of Lua (not an interpretation or translation to Lua), so the Lua code can be tested at ideone. –  Kyle Kanos 18 hours ago

Perl, 65

#!perl -p0
$.*=s/\Q$1/
/g while s/ ?(.)\z//;/
(.*)
/;$_=$.-1?null:"\"$1\""

This requires there is no newline character at in the second line of the input.

share|improve this answer
    
Nice job. This seems to be missing the double quotes though. –  Dennis 2 days ago
    
@Dennis, fixed. I misunderstood the example. –  nutki 2 days ago
1  
It's still missing the quotes for the null case. –  Dennis 2 days ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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