views:

1100

answers:

23

Create a method that:

Given a string, look for a mirror image (backwards) string at both the beginning and end of the given string. In other words, zero or more characters at the very beginning of the given string, and at the very end of the string in reverse order (possibly overlapping). For example, the string "abXYZba" has the mirror end "ab".

Examples

mirrorEnds("abXYZba") → "ab" 
mirrorEnds("abca") → "a"  
mirrorEnds("aba") → "aba"

Java solution:

public String mirrorEnds(String string) 
{
  boolean matches = true;
  StringBuilder mirror = new StringBuilder();
  int i = 0;
  int length = pString.length();

  while (matches && i < length) 
  {
    if (pString.charAt(i) == pString.charAt(length-i-1))
       mirror.append(pString.charAt(i));
    else
       matches = false;

    i++; 
   }

   String str = mirror.toString(); 
   return str;
}
+6  A: 

Ruby

class String
  def mirror_ends
    chars.zip(chars.reverse_each).take_while {|a, b| a == b }.map(&:first).join
  end
end

Testsuite:

require 'test/unit'
class TestMirrorEnds < Test::Unit::TestCase
  def test_that_abXYZba_mirror_ends_is_ab
    assert_equal 'ab', 'abXYZba'.mirror_ends
  end
  def test_that_abca_mirror_ends_is_a
    assert_equal 'a', 'abca'.mirror_ends
  end
  def test_that_aba_mirror_ends_is_aba
    assert_equal 'aba', 'aba'.mirror_ends
  end
end
Jörg W Mittag
Haha very nice.
Tony Ennis
+37  A: 

C++

#include <iostream>
#include <string>
#include <algorithm>
std::string mirrorEnds(const std::string& in)
{
    return std::string(in.begin(),
                       mismatch(in.begin(), in.end(), in.rbegin()).first);
}
int main()
{
    std::cout << mirrorEnds("abXYZba") << '\n'
              << mirrorEnds("abca") << '\n'
              << mirrorEnds("aba") << '\n';
}

EDIT: Since people are asking: in C++, any sequence can be represented as a pair of iterators, and any pair of iterators can become a sequence again. Here, the string in is viewed through the pair of iterators in.begin()...in.end() which present a view of the sequence going forward, and the same string in is viewed through a pair of iterators in.rbegin()...in.rend(), which represent a view of the sequence going backwards. std::mismatch() compares the two sequences that are given to it, element by element, until it finds a mismatch, which it returns as an iterator. Then the pair of iterators in.begin()...<return of mismatch> are viewed as a string again, and that string is returned.

Cubbi
+1: That's beautifully concise.
Mark E
can you put some words to explain the mismatch() call? not familiar with std
Chii
TokenMacGuy
+1: That's beautifully concise. Nice use of the STL.
André Caron
+1: I was thinking this was a text-book application of reverse iterators. Did not leave disappointed.
Boojum
Yep, that's the way to do it. Need to qualify `mismatch` with `std::` though.
Potatoswatter
@Potatoswatter: Why, ADL is supported everywhere.
Cubbi
@Cubbi: Ah, right. `std::string::iterator` may be a typedef of `char*`, though, so it only works because of the reverse_iterator. ADL is a fickle friend.
Potatoswatter
+8  A: 

Java

public static String mirrorEnds(String s) {
    int i = 0;
    while (i < s.length() && s.charAt(i) == s.charAt(s.length() - 1 - i))
        i++;
    return s.substring(0, i);
}
Sheldon L. Cooper
Whoooaaa.......
400_the_cat
+2  A: 

Scala

def mirrorEnds(s: String) =
  s.zip(s.reverse).takeWhile {p => p._1 == p._2}.map {_._1}.mkString
Jörg W Mittag
A: 

Python:

from itertools import takewhile
def mirrorEnds(s):
    return ''.join(a for a, b in takewhile(lambda p: p[0] == p[1], zip(s, reversed(s))))
Matthew Flaschen
+3  A: 

Common Lisp

(defun mirror-ends (string)
  (loop for i upfrom 0
        for j downfrom (1- (length string))
        while (and (<= i j) (char= (aref string i) (aref string j)))
        finally (return (subseq string 0 i))))
Robert Brown
+1 for lisp. See http://xkcd.com/297/
Tony Ennis
Is that the most concise way to do this in Lisp?
Thorbjørn Ravn Andersen
+3  A: 

C#

public static string MirrorEnds(this string s)
{
    return String.Join(
        "", from p in s.Zip(s.Reverse(), (a, b) => new { a, b }).
            TakeWhile(p => p.a == p.b) select p.a
    );
}
Jörg W Mittag
*Masterful!* Well done!
p.campbell
+1 for linq. +1 for single line. +1 for simplicity.
BrunoLM
Now that I noticed the extension method, +1 for that too. Indeed Masterful.
BrunoLM
@BrunoLM: I'm glad you like it, especially since I don't actually know C#.
Jörg W Mittag
+1  A: 

Tcl

The clearest way to do this I can think of is to convert the string into a list and compare with its reverse:

proc mirrorEnds {txt} {
    set x [split $txt {}]
    set y [lreverse $x]

    set mirror ""

    foreach a $x b $y {
        if {$a == $b} {
            append mirror $a
        } else {
            break
        }
    }

    return $mirror
}

Alternatively, you can do the standard iterate-from-both-directions thing. But it's more verbose:

proc mirrorEnds {txt} {
    set mirror ""

    for {set i 0} {$i < [string length $txt]} {incr i} {
        if {[string index $txt $i] == [string index $txt end-$i]} {
            append mirror [string index $txt $i]
        } else {
            break
        }
    }

    return $mirror
}
slebetman
+23  A: 

C#

Func<string, string> mirrorEnds =
    s => new string(s.Reverse().TakeWhile((c, i) => c == s[i]).ToArray());

For completeness, here was my initial take on it:

Func<string, string> mirrorEnds =
    s => new string(s.Zip(s.Reverse(), (a, b) => new { a, b })
                     .TakeWhile(c => c.a == c.b)
                     .Select(c => c.a).ToArray());

I changed it once I saw how close it was to Jorg's solution.

Gabe
The first thing I thought of was the Zip->Reverse->TakeWhile->Select, so I wrote it only to discover 5 other solutions doing the exact same thing. Thus, I came up with a more creative (and shorter) solution.
Gabe
+1 for linq. +1 for single line. +2 for simplicity.
BrunoLM
time to learn this C#
Cubbi
exceeds even most of the functional languages in conciseness. nice.
sreservoir
Very nice solution. +1. BTW: the reason why the `Zip(Reverse).TakeWhile.Select` is so popular, is probably because it is a direct 1:1 translation of the problem statement. Which is why I never understand why people think that code like that is complicated. I write code like that, not because I want to show off how smart I am, but because of how stupid I am. I cannot keep loop indices and termination conditions and off-by-one errors and fencepost errors and iterators straight. So, I simply eliminate them.
Jörg W Mittag
eh, Jorg's solution is pretty concise too...
Tony Ennis
Or more precisely: I let someone else (in this case the LINQ authors) worry about such things.
Jörg W Mittag
This is super! Thanks to LINQ.
Alex Essilfie
A: 

Java

Here's one way.

public static String reversi(String s) {
    StringBuffer sb2 = new StringBuffer(s).reverse();

    int i = 0;
    while (i < s.length() && s.charAt(i) == sb2.charAt(i)) i++;
    return i>0 ? s.substring(0, i) : "";
}
Tony Ennis
+1  A: 

Ruby

Inspired by @Sheldon L. Cooper's Java solution:

class String
  def mirror_ends
    chars.take_while.with_index {|c, i| c == self[-i-1] }.join
  end
end

Testsuite:

require 'test/unit'
class TestMirrorEnds < Test::Unit::TestCase
  def test_that_abXYZba_mirror_ends_is_ab
    assert_equal 'ab', 'abXYZba'.mirror_ends
  end
  def test_that_abca_mirror_ends_is_a
    assert_equal 'a', 'abca'.mirror_ends
  end
  def test_that_aba_mirror_ends_is_aba
    assert_equal 'aba', 'aba'.mirror_ends
  end
end
Jörg W Mittag
+5  A: 

C

  char *mirrorEnds(char *s)
  {
    char *a;
    for (a=s+strlen(s) ; *s && *s==*(a-1) ; s++,a--);
    return a;
  }
ring0
Why not for (a=s+strlen(s)-1; *s ..etc
WW
Nice! I like the way you return the substring.
Gabe
@WW the change you propose does not work: the returned `a` would be `1` before the actual position. Thus not working for `xyx` or showing `tx` in `xytx` (or would return `x` in `aaax` which is incorrect)
ring0
@Gabe thanks! no much extra storage involved ;-)
ring0
A: 

Perl

sub mirrorEnds {
  my ($a)=@_;
  my ($i,$b);
  for $i (1..length $a) {
    if (substr($a,0,$i) eq reverse(substr($a,-$i))) {
      $b = substr($a,0,$i);
    }
  }
  $b
}
socket puppet
+4  A: 

Haskell (somebody reformat this for me):

mirrorEnds a = map fst $ takeWhile (uncurry (==)) $ zip a (reverse a)

mirrorEnds a = zipWith const a $ takeWhile id $ zipWith (==) a (reverse a)

I actually like the second better.

sreservoir
I'd write the first as `mirrorEnds = ... $ zip . reverse` (points-free style rules). +1 for Haskell.
delnan
+1  A: 

C#

Here's a more conventional approach:

static string mirrorEnds(string strIn)
{
    string strOut = "";
    for (int i = 0, j = strIn.Length - 1; j >= 0 && strIn[i] == strIn[j]; i++, --j)
        strOut += strIn[i];
    return strOut;
}

And probably the fastest method:

static string mirrorEnds(string strIn)
{
    int i = 0, j = strIn.Length - 1;
    for (; j >= 0 && strIn[i] == strIn[j]; i++, --j) ;
    return strIn.Substring(0, i);
}
Gabe
A: 

PHP

$rev=str_split(strrev($str));
$mirror='';
foreach($rev as $k=>$v) {
    if($str[$k]==$v) {
        $mirror.=$v;
    } else {
        break;
    }
}
echo $mirror;
Naresh
+1  A: 

Delphi

function MirrorEnds(s: string): string;
var
  i, halfway: integer;
begin
  Result := '';
  halfway := Round((Length(s) / 2) - (1/2));  //halfway pt, rounded down
  for i := 1 to halfway do
    if s[Length(s)-i+1] = s[i] then
      Result := Result + s[i];
  if Length(Result) = halfway then
    Result := s;
end;

Or if you prefer a more code-golfy method (i.e., sacrifice performance for brevity) then you can do this:

function MirrorEnds(s: string): string;
var
  i: integer;
begin
  Result := '';
  for i := 1 to Length(s) do
    if ReverseString(s)[i] = s[i] then
      Result := Result + s[i]
    else
      Break;
end;

And finally, a brief test on my machine indicates that the first one is in fact about five times faster than the second one (although both are virtually instantaneous in practice):

Input string:"abcdefghijklmnopponmlkjihgfedcba"
# of iterations: 900000

Brief = 4973 ms
Fast = 1057 ms
JosephStyons
+3  A: 

Java

alternative

Didn't see the StringUtils version yet...

  String mirrorEnds(String s) {
    return StringUtils.getCommonPrefix(new String[] { s, s.reverse() });
  }
ring0
A: 

Python

alternative

def mirror_ends(string):
    return ''.join(string[i] for i in range(len(string)//2) if string[i] == string[-i-1])

>>> mirror_ends("abxyzba")
'ab'
Don O'Donnell
+1  A: 

XQuery

substring($s,1,min(let $c := string-to-codepoints($s)
                   return for $x at $p in $c
            where $x != $c[last() - $p + 1]
            return $p))
Nick Jones
+1 for novelty. Also interesting, because we have seen some LINQ already, and XQuery is where it got its syntax from.
Jörg W Mittag
A: 

GAWK-SED-SHELL Oneliner

echo string | sed 's/./& /g' | gawk '{ for(j=1; j<NF/2; j++) if($j==$(NF-j+1)) print $j; else break}' | tr -d "\n"

where string is the string to process.

athena
A: 

My Java Implementation

  public static String mirrorEnds(String in) {
    StringBuilder sb = new StringBuilder();
    char[] chars = in.toCharArray();
    int length = chars.length - 1;

    for (int i = 0; i < length; i++) {
        if (chars[i] == chars[length - i]) {
            sb.append(chars[i]);
        } else {
            break;
        }
    }

    return sb.toString();
}
Adam
A: 

Scheme

(define (equal-start? a b)
  (and
    (pair? a)
    (pair? b)
    (equal? (car a) (car b))))

(define (take-while-equal-start a b)
  (if (equal-start? a b)
      (cons
        (car a)
        (take-while-equal-start (cdr a) (cdr b)))
      '()))

(define (mirror-ends str)
  (let ((lst (string->list str)))
    (list->string
      (take-while-equal-start lst (reverse lst)))))

> (mirror-ends "abXYZba")
"ab"
> (mirror-ends "abca")
"a"
> (mirror-ends "aba")
"aba"
> (mirror-ends "")
""
> (mirror-ends "a")
"a"
lbruder