Middle three digits

From Rosetta Code
Revision as of 06:31, 8 February 2013 by rosettacode>Alansam (→‎{{header|NetRexx}}: a little cleanup)
Task
Middle three digits
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to:

Write a function/procedure/subroutine that is called with an integer value and returns the middle three digits of the integer if possible or a clear indication of an error if this is not possible.
Note: The order of the middle digits should be preserved.

Your function should be tested with the following values; the first line should return valid answers, those of the second line should return clear indications of an error:

123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345
1, 2, -1, -10, 2002, -2002, 0

Show your output on this page.

Ada

<lang Ada>with Ada.Text_IO;

procedure Middle_Three_Digits is

  Impossible: exception;
  function Middle_String(I: Integer; Middle_Size: Positive) return String is
     S: constant String := Integer'Image(I);
     First: Natural := S'First;
     Full_Size, Border: Natural;
  begin
     while S(First) not in '0' .. '9' loop -- skip leading blanks and minus
        First := First + 1;
     end loop;
     Full_Size := S'Last-First+1;
     if (Full_Size < Middle_Size) or (Full_Size mod 2 = 0) then
        raise Impossible;
     else
        Border := (Full_Size - Middle_Size)/2;
        return S(First+Border .. First+Border+Middle_Size-1);
     end if;
  end Middle_String;
  Inputs: array(Positive range <>) of Integer :=
    (123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345,
     1, 2, -1, -10, 2002, -2002, 0);
  Error_Message: constant String := "number of digits must be >= 3 and odd";
  package IIO is new Ada.Text_IO.Integer_IO(Integer);

begin

  for I in Inputs'Range loop
     IIO.Put(Inputs(I), Width => 9);
     Ada.Text_IO.Put(": ");
     begin
        Ada.Text_IO.Put(Middle_String(Inputs(I), 3));
     exception
        when Impossible => Ada.Text_IO.Put("****" & Error_Message & "****");
     end;
     Ada.Text_IO.New_Line;
  end loop;

end Middle_Three_Digits;</lang>

Output:
      123: 123
    12345: 234
  1234567: 345
987654321: 654
    10001: 000
   -10001: 000
     -123: 123
     -100: 100
      100: 100
   -12345: 234
        1: ****number of digits must be >= 3 and odd****
        2: ****number of digits must be >= 3 and odd****
       -1: ****number of digits must be >= 3 and odd****
      -10: ****number of digits must be >= 3 and odd****
     2002: ****number of digits must be >= 3 and odd****
    -2002: ****number of digits must be >= 3 and odd****
        0: ****number of digits must be >= 3 and odd****

C++

<lang C++>

  1. include <iostream>
  2. include <sstream>
  3. include <string>

// @author Martin Ettl // @date 2013-02-04

/**

* Convert variables of type T to std::string
*
*
* @param d --> digit of type T
*
* @return <-- the corresponding string value
*/

template <typename T> const std::string toString(const T &d) {

   std::ostringstream result;
   result << d;
   return result.str();

}

/**

* Determine the middle n digits of the integer. If it is not possible to determine the
* the middle n digits, an empty string is provided.
*
* @param iDigit --> The digit to test
* @param n      --> The number of digits inbetween
*
* @return <-- the middle three digits
*/

std::string strMiddleNDigits(int iDigit, const int &n) {

   // is negative: --> convert to a positive number
   if(iDigit<0)
   {
       iDigit*=-1;
   }
   // convert to string
   std::string strNumber (toString(iDigit));
   size_t len(strNumber.length());
   if( (len < n) || (len % 2 == 0) )
   {
       return "";
   }
   size_t mid(len/2);
   return strNumber.substr(mid-n/2, n);

}

/**

* Determine the middle three digits of the integer. If it is not possible to determine the
* the middle three digits, an empty string is provided.
*
* @param iDigit --> The digit to test
*
* @return <-- the middle three digits
*/

std::string strMiddleThreeDigits(int iDigit) {

   return strMiddleNDigits(iDigit,3);

}

int main() {

   const int iPassing[] = {123, 12345, 1234567, 987654321, 10001, -10001,
                           -123, -100, 100, -12345
                          };
   for(unsigned int ui = 0; ui < 10; ++ui)
   {
       std::cout << "strMiddleThreeDigits("<< iPassing[ui] <<"): "
                 << strMiddleThreeDigits(iPassing[ui])<< "\n";
   }
   const int iFailing[] = {1, 2, -1, -10, 2002, -2002, 0};
   for(unsigned int ui = 0; ui < 7; ++ui)
   {
       std::string strResult = strMiddleThreeDigits(iFailing[ui]);
       std::cout << "strMiddleThreeDigits("<< iFailing[ui] <<"): "
                 << (strResult.empty()?"Need odd and >= 3 digits":strResult)
                 << "\n";
   }
   return 0;

} </lang>

Output:
strMiddleThreeDigits(123): 123
strMiddleThreeDigits(12345): 234
strMiddleThreeDigits(1234567): 345
strMiddleThreeDigits(987654321): 654
strMiddleThreeDigits(10001): 000
strMiddleThreeDigits(-10001): 000
strMiddleThreeDigits(-123): 123
strMiddleThreeDigits(-100): 100
strMiddleThreeDigits(100): 100
strMiddleThreeDigits(-12345): 234
strMiddleThreeDigits(1): Need odd and >= 3 digits
strMiddleThreeDigits(2): Need odd and >= 3 digits
strMiddleThreeDigits(-1): Need odd and >= 3 digits
strMiddleThreeDigits(-10): Need odd and >= 3 digits
strMiddleThreeDigits(2002): Need odd and >= 3 digits
strMiddleThreeDigits(-2002): Need odd and >= 3 digits
strMiddleThreeDigits(0): Need odd and >= 3 digits

D

<lang d>import std.stdio, std.traits, std.conv;

string middleThreeDigits(T)(in T n) if (isIntegral!T) {

   auto s = n < 0 ? n.text()[1 .. $] : n.text();
   auto len = s.length;
   if (len < 3 || len % 2 == 0)
       return "Need odd and >= 3 digits";
   auto mid = len / 2;
   return s[mid - 1 .. mid + 2];

}

void main() {

   immutable passing = [123, 12345, 1234567, 987654321, 10001, -10001,
           -123, -100, 100, -12345, long.min, long.max];
   foreach (n; passing)
       writefln("middleThreeDigits(%s): %s", n, middleThreeDigits(n));
   immutable failing = [1, 2, -1, -10, 2002, -2002, 0,int.min,int.max];
   foreach (n; failing)
       writefln("middleThreeDigits(%s): %s", n, middleThreeDigits(n));

}</lang>

Output:
middleThreeDigits(123): 123
middleThreeDigits(12345): 234
middleThreeDigits(1234567): 345
middleThreeDigits(987654321): 654
middleThreeDigits(10001): 000
middleThreeDigits(-10001): 000
middleThreeDigits(-123): 123
middleThreeDigits(-100): 100
middleThreeDigits(100): 100
middleThreeDigits(-12345): 234
middleThreeDigits(-9223372036854775808): 368
middleThreeDigits(9223372036854775807): 368
middleThreeDigits(1): Need odd and >= 3 digits
middleThreeDigits(2): Need odd and >= 3 digits
middleThreeDigits(-1): Need odd and >= 3 digits
middleThreeDigits(-10): Need odd and >= 3 digits
middleThreeDigits(2002): Need odd and >= 3 digits
middleThreeDigits(-2002): Need odd and >= 3 digits
middleThreeDigits(0): Need odd and >= 3 digits
middleThreeDigits(-2147483648): Need odd and >= 3 digits
middleThreeDigits(2147483647): Need odd and >= 3 digits

Alternative Version

This longer version gives a stronger typed output, and it tries to be faster avoiding conversions to string. <lang d>import std.stdio, std.traits, std.math, std.variant;

/// Returns a string with the error, or the three digits. Algebraic!(string, char[3]) middleThreeDigits(T)(in T n) if (isIntegral!T) {

   // Awkward code to face abs(T.min) when T is signed.
   ulong ln;
   static if (isSigned!T) {
       if (n >= 0) {
           ln = n;
       } else {
           if (n == T.min) {
               ln = -(n + 1);
               ln++;
           } else {
               ln = -n;
           }
       }
   } else {
       ln = n;
   }
   if (ln < 100)
       return typeof(return)("n is too short.");
   immutable uint digits = 1 + cast(uint)log10(ln);
   if (digits % 2 == 0)
       return typeof(return)("n must have an odd number of digits.");
   // From the Reddit answer by "millstone".
   int drop = (digits - 3) / 2;
   while (drop-- > 0)
       ln /= 10;
   char[3] result = void;
   result[2] = ln % 10 + '0';
   ln /= 10;
   result[1] = ln % 10 + '0';
   ln /= 10;
   result[0] = ln % 10 + '0';
   return typeof(return)(result);

}

void main() {

   immutable passing = [123, 12345, 1234567, 987654321, 10001,
                        -10001, -123, -100, 100, -12345, -8765432];
   foreach (n; passing) {
       auto mtd = middleThreeDigits(n);
       // A string result means it didn't pass.
       assert(!mtd.peek!string);
       writefln("middleThreeDigits(%d): %s", n, mtd);
   }
   writeln();
   immutable failing = [1, 2, -1, -10, 2002, -2002, 0,
                        15, int.min, int.max];
   foreach (n; failing) {
       auto mtd = middleThreeDigits(n);
       assert(mtd.peek!string);
       writefln("middleThreeDigits(%d): %s", n, mtd);
   }
   writeln();
   immutable long[] passingL = [123, 12345, 1234567, 987654321, 10001,
                                -10001, -123, -100, 100, -12345,
                                -8765432, long.min, long.max];
   foreach (n; passingL) {
       auto mtd = middleThreeDigits(n);
       assert(!mtd.peek!string);
       writefln("middleThreeDigits(%d): %s", n, mtd);
   }
   writeln();
   immutable long[] failingL = [1, 2, -1, -10, 2002, -2002, 0, 15];
   foreach (n; failingL) {
       auto mtd = middleThreeDigits(n);
       assert(mtd.peek!string);
       writefln("middleThreeDigits(%d): %s", n, mtd);
   }
   writeln();
   {
       immutable n = short.min;
       auto mtd = middleThreeDigits(n);
       assert(!mtd.peek!string);
       writefln("middleThreeDigits(cast(short)%d): %s", n, mtd);
   }

}</lang>

Output:
middleThreeDigits(123): 123
middleThreeDigits(12345): 234
middleThreeDigits(1234567): 345
middleThreeDigits(987654321): 654
middleThreeDigits(10001): 000
middleThreeDigits(-10001): 000
middleThreeDigits(-123): 123
middleThreeDigits(-100): 100
middleThreeDigits(100): 100
middleThreeDigits(-12345): 234
middleThreeDigits(-8765432): 654

middleThreeDigits(1): n is too short.
middleThreeDigits(2): n is too short.
middleThreeDigits(-1): n is too short.
middleThreeDigits(-10): n is too short.
middleThreeDigits(2002): n must have an odd number of digits.
middleThreeDigits(-2002): n must have an odd number of digits.
middleThreeDigits(0): n is too short.
middleThreeDigits(15): n is too short.
middleThreeDigits(-2147483648): n must have an odd number of digits.
middleThreeDigits(2147483647): n must have an odd number of digits.

middleThreeDigits(123): 123
middleThreeDigits(12345): 234
middleThreeDigits(1234567): 345
middleThreeDigits(987654321): 654
middleThreeDigits(10001): 000
middleThreeDigits(-10001): 000
middleThreeDigits(-123): 123
middleThreeDigits(-100): 100
middleThreeDigits(100): 100
middleThreeDigits(-12345): 234
middleThreeDigits(-8765432): 654
middleThreeDigits(-9223372036854775808): 368
middleThreeDigits(9223372036854775807): 368

middleThreeDigits(1): n is too short.
middleThreeDigits(2): n is too short.
middleThreeDigits(-1): n is too short.
middleThreeDigits(-10): n is too short.
middleThreeDigits(2002): n must have an odd number of digits.
middleThreeDigits(-2002): n must have an odd number of digits.
middleThreeDigits(0): n is too short.
middleThreeDigits(15): n is too short.

middleThreeDigits(cast(short)-32768): 276

J

Solution: <lang j>asString=: ":"0 NB. convert vals to strings getPfxSize=: [: -:@| 3 -~ # NB. get size of prefix to drop before the 3 middle digits getMid3=: (3 {. getPfxSize }. ,&'err') :: ('err'"_) NB. get 3 middle digits or return 'err' getMiddle3=: getMid3@asString@:|</lang> Example: <lang j> vals=: 123 12345 1234567 987654321 10001 _10001 _123 _100 100 _12345 1 2 _1 _10 2002 _2002 0

  getMiddle3 vals

123 234 345 654 000 000 123 100 100 234 err err err err err err err</lang>

Java

<lang Java>public class MiddleThreeDigits {

   public static void main(String[] args) {
       final long[] passing = {123, 12345, 1234567, 987654321, 10001, -10001,
           -123, -100, 100, -12345, Long.MIN_VALUE, Long.MAX_VALUE};
       final int[] failing = {1, 2, -1, -10, 2002, -2002, 0, Integer.MIN_VALUE,
           Integer.MAX_VALUE};
       for (long n : passing)
           System.out.printf("middleThreeDigits(%s): %s\n", n, middleThreeDigits(n));
       for (int n : failing)
           System.out.printf("middleThreeDigits(%s): %s\n", n, middleThreeDigits(n));
   }
   public static <T> String middleThreeDigits(T n) {
       String s = String.valueOf(n);
       if (s.charAt(0) == '-')
           s = s.substring(1);
       int len = s.length();
       if (len < 3 || len % 2 == 0)
           return "Need odd and >= 3 digits";
       int mid = len / 2;
       return s.substring(mid - 1, mid + 2);
   }

}</lang>

middleThreeDigits(123): 123
middleThreeDigits(12345): 234
middleThreeDigits(1234567): 345
middleThreeDigits(987654321): 654
middleThreeDigits(10001): 000
middleThreeDigits(-10001): 000
middleThreeDigits(-123): 123
middleThreeDigits(-100): 100
middleThreeDigits(100): 100
middleThreeDigits(-12345): 234
middleThreeDigits(-9223372036854775808): 368
middleThreeDigits(9223372036854775807): 368
middleThreeDigits(1): Need odd and >= 3 digits
middleThreeDigits(2): Need odd and >= 3 digits
middleThreeDigits(-1): Need odd and >= 3 digits
middleThreeDigits(-10): Need odd and >= 3 digits
middleThreeDigits(2002): Need odd and >= 3 digits
middleThreeDigits(-2002): Need odd and >= 3 digits
middleThreeDigits(0): Need odd and >= 3 digits
middleThreeDigits(-2147483648): Need odd and >= 3 digits
middleThreeDigits(2147483647): Need odd and >= 3 digits

NetRexx

<lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols nobinary

sl = '123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345' -

    '1 2 -1 -10 2002 -2002 0' -
    'abc 1e3 -17e-3 4004.5 12345678 9876543210' -- extras

parse arg digsL digsR . if \digsL.datatype('w') then digsL = 3 if \digsR.datatype('w') then digsR = digsL if digsL > digsR then digsR = digsL

loop dc = digsL to digsR

 say 'Middle' dc 'characters'
 loop nn = 1 to sl.words()
   val = sl.word(nn)
   say middleDigits(dc, val)
   end nn
 say
 end dc

return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method middleDigits(didgitCt, val) constant

 text = val.right(15)':'
 even = didgitCt // 2 == 0 -- odd or even?
 select
   when \val.datatype('w')                 then text = text 'is not a whole number'
   when val.abs().length < didgitCt        then text = text 'has less than' didgitCt 'digits'
   when \even & val.abs().length // 2 == 0 then text = text 'does not have an odd number of digits'
   when even  & val.abs().length // 2 \= 0 then text = text 'does not have an even number of digits'
   otherwise do
     val = val.abs()
     valL = val.length
     cutP = (valL - didgitCt) % 2
     text = text val.substr(cutP + 1, didgitCt)
     end
   catch NumberFormatException
     text = val 'is not numeric'
   end
 return text

</lang> Output:

Middle 3 characters
            123: 123
          12345: 234
        1234567: 345
      987654321: 654
          10001: 000
         -10001: 000
           -123: 123
           -100: 100
            100: 100
         -12345: 234
              1: has less than 3 digits
              2: has less than 3 digits
             -1: has less than 3 digits
            -10: has less than 3 digits
           2002: does not have an odd number of digits
          -2002: does not have an odd number of digits
              0: has less than 3 digits
            abc: is not a whole number
            1e3: is not a whole number
         -17e-3: is not a whole number
         4004.5: is not a whole number
       12345678: does not have an odd number of digits
     9876543210: does not have an odd number of digits

OCaml

<lang ocaml>let even x = (x land 1) <> 1

let middle_three_digits x =

 let s = string_of_int (abs x) in
 let n = String.length s in
 if n < 3 then failwith "need >= 3 digits" else
 if even n then failwith "need odd number of digits" else
 String.sub s (n / 2 - 1) 3

let passing = [123; 12345; 1234567; 987654321; 10001; -10001; -123; -100; 100; -12345] let failing = [1; 2; -1; -10; 2002; -2002; 0]

let print x =

 let res =
   try (middle_three_digits x)
   with Failure e -> "failure: " ^ e
 in
 Printf.printf "%d: %s\n" x res

let () =

 print_endline "Should pass:";
 List.iter print passing;
 print_endline "Should fail:";
 List.iter print failing;
</lang>
Output:
Should pass:
123: 123
12345: 234
1234567: 345
987654321: 654
10001: 000
-10001: 000
-123: 123
-100: 100
100: 100
-12345: 234

Should fail:
1: failure: need >= 3 digits
2: failure: need >= 3 digits
-1: failure: need >= 3 digits
-10: failure: need >= 3 digits
2002: failure: need odd number of digits
-2002: failure: need odd number of digits
0: failure: need >= 3 digits

Perl

<lang Perl>#!/usr/bin/perl use strict ; use warnings ;

sub middlethree {

  my $number = shift ;
  my $testnumber = abs $number ;
  my $error = "Middle 3 digits can't be shown" ;
  my $numberlength = length $testnumber ;
  if ( $numberlength < 3 ) {
     print "$error : $number too short!\n" ;
     return ;
  }
  if ( $numberlength % 2 == 0 ) {
     print "$error : even number of digits in $number!\n" ;
     return ;
  }
  my $middle = int ( $numberlength  / 2 ) ;
  print "Middle 3 digits of $number : " . substr( $testnumber , $middle - 1 , 3 ) . " !\n" ;
  return ;

}

my @numbers = ( 123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345 ,

     1, 2, -1, -10, 2002, -2002, 0 ) ;

map { middlethree( $_ ) } @numbers ; </lang>

Output:
Middle 3 digits of 123 : 123 !
Middle 3 digits of 12345 : 234 !
Middle 3 digits of 1234567 : 345 !
Middle 3 digits of 987654321 : 654 !
Middle 3 digits of 10001 : 000 !
Middle 3 digits of -10001 : 000 !
Middle 3 digits of -123 : 123 !
Middle 3 digits of -100 : 100 !
Middle 3 digits of 100 : 100 !
Middle 3 digits of -12345 : 234 !
Middle 3 digits can't be shown : 1 too short!
Middle 3 digits can't be shown : 2 too short!
Middle 3 digits can't be shown : -1 too short!
Middle 3 digits can't be shown : -10 too short!
Middle 3 digits can't be shown : even number of digits in 2002!
Middle 3 digits can't be shown : even number of digits in -2002!
Middle 3 digits can't be shown : 0 too short!

Perl 6

<lang Perl6>sub middle-three($n) {

   given $n.abs {
       when .chars < 3  { "$n is too short" }
       when .chars %% 2 { "$n has an even number of digits" }
       default          { "The three middle digits of $n are: ", .substr: (.chars - 3)/2, 3 }
   }

}

say middle-three($_) for <

   123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345
   1 2 -1 -10 2002 -2002 0

>;</lang>

Output:
The three middle digits of 123 are:  123
The three middle digits of 12345 are:  234
The three middle digits of 1234567 are:  345
The three middle digits of 987654321 are:  654
The three middle digits of 10001 are:  000
The three middle digits of -10001 are:  000
The three middle digits of -123 are:  123
The three middle digits of -100 are:  100
The three middle digits of 100 are:  100
The three middle digits of -12345 are:  234
1 is too short
2 is too short
-1 is too short
-10 is too short
2002 has an even number of digits
-2002 has an even number of digits
0 is too short

Python

<lang python>>>> def middle_three_digits(i): s = str(abs(i)) length = len(s) assert length >= 3 and length % 2 == 1, "Need odd and >= 3 digits" mid = length // 2 return s[mid-1:mid+2]

>>> passing = [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345] >>> failing = [1, 2, -1, -10, 2002, -2002, 0] >>> for x in passing + failing: try: answer = middle_three_digits(x) except AssertionError as error: answer = error print("middle_three_digits(%s) returned: %r" % (x, answer))


middle_three_digits(123) returned: '123' middle_three_digits(12345) returned: '234' middle_three_digits(1234567) returned: '345' middle_three_digits(987654321) returned: '654' middle_three_digits(10001) returned: '000' middle_three_digits(-10001) returned: '000' middle_three_digits(-123) returned: '123' middle_three_digits(-100) returned: '100' middle_three_digits(100) returned: '100' middle_three_digits(-12345) returned: '234' middle_three_digits(1) returned: AssertionError('Need odd and >= 3 digits',) middle_three_digits(2) returned: AssertionError('Need odd and >= 3 digits',) middle_three_digits(-1) returned: AssertionError('Need odd and >= 3 digits',) middle_three_digits(-10) returned: AssertionError('Need odd and >= 3 digits',) middle_three_digits(2002) returned: AssertionError('Need odd and >= 3 digits',) middle_three_digits(-2002) returned: AssertionError('Need odd and >= 3 digits',) middle_three_digits(0) returned: AssertionError('Need odd and >= 3 digits',) >>> </lang>

REXX

<lang rexx>/* REXX ***************************************************************

  • 03.02.2013 Walter Pachl
                                                                                                                                            • /

sl='123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345',

  '2 -1 -10 2002 -2002 0 abc 1e3 -17e-3'

Do While sl<> /* loop through test values */

 Parse Var sl s sl                    /* pick next value            */
 Call mid3 s                          /* test it                    */
 End

Exit mid3: Procedure Parse arg d /* take the argument */ Select /* first test for valid input */

 When datatype(d)<>'NUM'   Then Call error 'not a number'
 When pos('E',translate(d))>0 Then Call error 'not just digits'
 When length(abs(d))<3     Then Call error 'less than 3 digits'
 When length(abs(d))//2<>1 Then Call error 'not an odd number of digits'
 Otherwise Do                         /* input is ok                */
   dx=abs(d)                          /* get rid of optional sign   */
   ld=length(dx)                      /* length of digit string     */
   z=(ld-3)/2                         /* number of digits to cut    */
   Say left(d,12) '->' substr(dx,z+1,3) /* show middle 3 digits     */
   End
 End
 Return

error:

 Say left(d,12) '->' arg(1)           /* tell about the problem     */
 Return

</lang> Output:

123          -> 123
12345        -> 234
1234567      -> 345
987654321    -> 654
10001        -> 000
-10001       -> 000
-123         -> 123
-100         -> 100
100          -> 100
-12345       -> 234
2            -> less than 3 digits
-1           -> less than 3 digits
-10          -> less than 3 digits
2002         -> not an odd number of digits
-2002        -> not an odd number of digits
0            -> less than 3 digits
abc          -> not a number
1e3          -> not just digits
-17e-3       -> not just digits

Ruby

<lang ruby>def middle_three_digits(n)

  # minus sign doesn't factor into digit count,
  # and calling #abs acts as a duck-type assertion
  n = n.abs
  # convert to string and find length
  l = (s = n.to_s).length
  # check validity
  raise ArgumentError, "Number must have at least three digits" if l < 3
  raise ArgumentError, "Number must have an odd number of digits" if l % 2 == 0
  return s[l/2-1,3].to_i

end

samples = [

 123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345,
 1, 2, -1, -10, 2002, -2002, 0 

]

width = samples.map { |n| n.to_s.length }.max

samples.each do |n|

  print "%#{width}d: " % n
  begin
    puts "%03d" % middle_three_digits(n)
  rescue ArgumentError => e
    puts e.to_s
  end

end</lang> Output:

      123: 123
    12345: 234
  1234567: 345
987654321: 654
    10001: 000
   -10001: 000
     -123: 123
     -100: 100
      100: 100
   -12345: 234
        1: Number must have at least three digits
        2: Number must have at least three digits
       -1: Number must have at least three digits
      -10: Number must have at least three digits
     2002: Number must have an odd number of digits
    -2002: Number must have an odd number of digits
        0: Number must have at least three digits

Rust

<lang rust>fn middle_three_digits(x: int) -> Result<~str, ~str> {

   let s = int::abs(x).to_str();
   let len = s.len();
   if len < 3 {
       Err(~"Too short")
   } else if len % 2 == 0 {
       Err(~"Even number of digits")
   } else {
       Ok(s.slice(len/2 - 1, len/2 + 2))
   }

}

fn print_result(x: int) {

   io::print(fmt!("middle_three_digits(%?) returned: ", x));
   match middle_three_digits(x) {
       Ok(move s) => io::println(fmt!("Success, %s", s)),
       Err(move s) => io::println(fmt!("Failure, %s", s))
   }

}

fn main() {

   let passing = [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345];
   let failing = [1, 2, -1, -10, 2002, -2002, 0];
   for passing.each |i| {
       print_result(*i);
   }
   for failing.each |i| {
       print_result(*i);
   }

}</lang>

Output:

middle_three_digits(123) returned: Success, 123
middle_three_digits(12345) returned: Success, 234
middle_three_digits(1234567) returned: Success, 345
middle_three_digits(987654321) returned: Success, 654
middle_three_digits(10001) returned: Success, 000
middle_three_digits(-10001) returned: Success, 000
middle_three_digits(-123) returned: Success, 123
middle_three_digits(-100) returned: Success, 100
middle_three_digits(100) returned: Success, 100
middle_three_digits(-12345) returned: Success, 234
middle_three_digits(1) returned: Failure, Too short
middle_three_digits(2) returned: Failure, Too short
middle_three_digits(-1) returned: Failure, Too short
middle_three_digits(-10) returned: Failure, Too short
middle_three_digits(2002) returned: Failure, Even number of digits
middle_three_digits(-2002) returned: Failure, Even number of digits
middle_three_digits(0) returned: Failure, Too short

Scala

<lang scala>/**

* Optionally return the middle three digits of an integer.
*
* @example List(123,12345,-789,1234,12) flatMap (middleThree(_)), returns: List(123, 234, 789)
*/

def middleThree( s:Int ) : Option[Int] = s.abs.toString match {

 case v if v.length % 2 == 0   => None   // Middle three is undefined for even lengths
 case v if v.length < 3        => None
 case v                        => 			
   val i = (v.length / 2) - 1
   Some( v.substring(i,i+3).toInt )

}


// A little test... val intVals = List(123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345,1,2,-1,-10,2002,-2002,0)

intVals map (middleThree(_)) map {

 case None => "No middle three" 
 case Some(v) => "%03d".format(v)  // Format the value, force leading zeroes 

} mkString("\n") </lang>

Output:
123
234
345
654
000
000
123
100
100
234
No middle three
No middle three
No middle three
No middle three
No middle three
No middle three
No middle three

UNIX Shell

Works with: Bourne Again Shell
Works with: Korn Shell version 93
Works with: Z Shell

<lang bash>function middle3digits {

 typeset -i n="${1#-}"
 typeset -i l=${#n}
 if (( l < 3 )); then
   echo >&2 "$1 has less than 3 digits"
   return 1
 elif (( l % 2 == 0 )); then
   echo >&2 "$1 has an even number of digits"
   return 1
 else
   echo ${n:$((l/2-1)):3}
   return 0
 fi

}

  1. test

testdata=(123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345 1 2 -1

         -10 2002 -2002 0)

for n in ${testdata[@]}; do

 printf "%10d: " $n
 middle3digits "$n"

done</lang>

Output:

       123: 123
     12345: 234
   1234567: 345
 987654321: 654
     10001: 000
    -10001: 000
      -123: 123
      -100: 100
       100: 100
    -12345: 234
         1: 1 has less than 3 digits
         2: 2 has less than 3 digits
        -1: -1 has less than 3 digits
       -10: -10 has less than 3 digits
      2002: 2002 has an even number of digits
     -2002: -2002 has an even number of digits
         0: 0 has less than 3 digits

Vedit macro language

<lang vedit>do {

   #1 = Get_Num("Enter a number, or 0 to stop: ", STATLINE)
   Ins_Text("Input: ") Num_Ins(#1, COUNT, 10)
   Call("MIDDLE_3_DIGITS")
   Ins_Text("  Result: ") Reg_Ins(10) Ins_Newline
   Update()

} while (#1); Return

// Find middle 3 digits of a number // in: #1 = numeric value // out: @10 = the result, or error text //

MIDDLE_3_DIGITS:

Buf_Switch(Buf_Free) Num_Ins(abs(#1), LEFT+NOCR) // the input value as string

  1. 2 = Cur_Col-1 // #2 = number of digits

if (#2 < 3) {

   Reg_Set(10, "Too few digits!")

} else {

   if ((#2 & 1) == 0) {

Reg_Set(10, "Not odd number of digits!")

   } else {

Goto_Pos((#2-3)/2) Reg_Copy_Block(10, Cur_Pos, Cur_Pos+3)

   }

} Buf_Quit(OK) Return </lang>

Output:

Input:        123  Result: 123
Input:      12345  Result: 234
Input:    1234567  Result: 345
Input:  987654321  Result: 654
Input:      10001  Result: 000
Input:     -10001  Result: 000
Input:       -123  Result: 123
Input:       -100  Result: 100
Input:        100  Result: 100
Input:     -12345  Result: 234
Input:          1  Result: Too few digits!
Input:          2  Result: Too few digits!
Input:         -1  Result: Too few digits!
Input:        -10  Result: Too few digits!
Input:       2002  Result: Not odd number of digits!
Input:      -2002  Result: Not odd number of digits!
Input:          0  Result: Too few digits! 

XPL0

<lang XPL0>include c:\cxpl\stdlib;

func Mid3Digits(I); \Return the middle three digits of I int I; int Len, Mid; char S(10); [ItoA(abs(I), S); Len:= StrLen(S); if Len<3 or (Len&1)=0 then return "Must be 3, 5, 7 or 9 digits"; Mid:= Len/2; S:= S + Mid - 1; S(2):= S(2) ! $80; \terminate string return S; \WARNING: very temporary ];

int Passing, Failing, X; [Passing:= [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345];

Failing:= [1, 2, -1, -10, 2002, -2002, 0];     \WARNING: nasty trick

for X:= 0 to 16 do

   [Text(0, "Middle three digits of ");  IntOut(0, Passing(X));
    Text(0, " returned: ");
    Text(0, Mid3Digits(Passing(X)));  CrLf(0);
   ];

]</lang>

Output:
Middle three digits of 123 returned: 123
Middle three digits of 12345 returned: 234
Middle three digits of 1234567 returned: 345
Middle three digits of 987654321 returned: 654
Middle three digits of 10001 returned: 000
Middle three digits of -10001 returned: 000
Middle three digits of -123 returned: 123
Middle three digits of -100 returned: 100
Middle three digits of 100 returned: 100
Middle three digits of -12345 returned: 234
Middle three digits of 1 returned: Must be 3, 5, 7 or 9 digits
Middle three digits of 2 returned: Must be 3, 5, 7 or 9 digits
Middle three digits of -1 returned: Must be 3, 5, 7 or 9 digits
Middle three digits of -10 returned: Must be 3, 5, 7 or 9 digits
Middle three digits of 2002 returned: Must be 3, 5, 7 or 9 digits
Middle three digits of -2002 returned: Must be 3, 5, 7 or 9 digits
Middle three digits of 0 returned: Must be 3, 5, 7 or 9 digits