Middle three digits

From Rosetta Code
Jump to: navigation, search
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.

Contents

[edit] 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;
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****

[edit] Aime

void
m3(integer i)
{
text s;
 
s = itoa(i);
if (character(s, 0) == '-') {
s = delete(s, 0);
}
 
if (length(s) < 3) {
v_integer(i);
v_text(" has not enough digits\n");
} elif (length(s) & 1) {
o_winteger(9, i);
o_text(": ");
o_text(cut(s, length(s) - 3 >> 1, 3));
o_byte('\n');
} else {
v_integer(i);
v_text(" has an even number of digits\n");
}
}
 
void
middle_3(...)
{
integer i;
 
i = 0;
while (i < count()) {
m3($i);
i += 1;
}
}
 
integer
main(void)
{
middle_3(123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100,
-12345, 1, 2, -1, -10, 2002, -2002, 0);
 
return 0;
}
Output:
      123: 123
    12345: 234
  1234567: 345
987654321: 654
    10001: 000
   -10001: 000
     -123: 123
     -100: 100
      100: 100
   -12345: 234
1 has not enough digits
2 has not enough digits
-1 has not enough digits
-10 has not enough digits
2002 has an even number of digits
-2002 has an even number of digits
0 has not enough digits

[edit] ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.6.win32
# we define a UNION MODE so that our middle 3 digits PROC can #
# return either an integer on success or a error message if #
# the middle 3 digits couldn't be extracted #
 
MODE EINT = UNION( INT # success value #, STRING # error message # );
 
 
# PROC to return the middle 3 digits of an integer. #
# if this is not possible, an error message is returned #
# instead #
 
PROC middle 3 digits = ( INT number ) EINT:
BEGIN
 
# convert the absolute value of the number to a string with the #
# minumum possible number characters #
STRING digits = whole( ABS number, 0 );
INT len = UPB digits;
 
 
IF len < 3
THEN
# number has less than 3 digits #
# return an error message #
 
"number must have at least three digits"
 
ELIF ( len MOD 2 ) = 0
THEN
# the number has an even number of digits #
# return an error message #
 
"number must have an odd number of digits"
 
ELSE
# the number is suitable for extraction of the middle 3 digits #
 
INT first digit pos = 1 + ( ( len - 3 ) OVER 2 );
 
# the result is the integer value of the three digits #
 
( ( ( ABS digits[ first digit pos ] - ABS "0" ) * 100 )
+ ( ( ABS digits[ first digit pos + 1 ] - ABS "0" ) * 10 )
+ ( ( ABS digits[ first digit pos + 2 ] - ABS "0" ) )
)
 
FI
 
END; # middle 3 digits #
 
 
 
main: (
 
# test the middle 3 digits PROC #
 
[]INT test values = ( 123, 12345, 1234567, 987654321
, 10001, -10001, -123, -100
, 100, -12345
# the following values should fail #
, 1, 2, -1, -10, 2002, -2002, 0
);
 
FOR test number FROM LWB test values TO UPB test values
DO
 
CASE middle 3 digits( test values[ test number ] )
IN
( INT success value ): # got the middle 3 digits #
 
printf( ( $ 11z-d, " : ", 3d $
, test values[ test number ]
, success value
)
)
,
 
( STRING error message ): # got an error message #
 
printf( ( $ 11z-d, " : ", n( UPB error message )a $
, test values[ test number ]
, error message
)
)
 
ESAC;
 
print( ( newline ) )
 
OD
 
)
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

[edit] AutoHotkey

Numbers:="123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345,1,2,-1,-10,2002,-2002,0"
Loop, parse, Numbers, `,
{
if A_LoopField is not number
log := log . A_LoopField . "`t: Not a valid number`n"
else if((d:=StrLen(n:=RegExReplace(A_LoopField,"\D")))<3)
log := log . A_LoopField . "`t: Too short`n"
else if(!Mod(d,2))
log := log . A_LoopField . "`t: Not an odd number of digits`n"
else
log := log . A_LoopField . "`t: " . SubStr(n,((d-3)//2)+1,3) . "`n"
}
MsgBox % log
Output:
123	: 123
12345	: 234
1234567	: 345
987654321	: 654
10001	: 000
-10001	: 000
-123	: 123
-100	: 100
100	: 100
-12345	: 234
1	: Too short
2	: Too short
-1	: Too short
-10	: Too short
2002	: Not an odd number of digits
-2002	: Not an odd number of digits
0	: Too short

[edit] AWK

#!/bin/awk -f
# use as: awk -f middle_three_digits.awk
 
BEGIN {
n = split("123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345 1 2 -1 -10 2002 -2002 0", arr)
 
for (i=1; i<=n; i++) {
if (arr[i] !~ /^-?[0-9]+$/) {
printf("%10s : invalid input: not a number\n", arr[i])
continue
}
 
num = arr[i]<0 ? -arr[i]:arr[i]
len = length(num)
 
if (len < 3) {
printf("%10s : invalid input: too few digits\n", arr[i])
continue
}
 
if (len % 2 == 0) {
printf("%10s : invalid input: even number of digits\n", arr[i])
continue
}
 
printf("%10s : %s\n", arr[i], substr(num, len/2, 3))
}
}
 
Output:
       123 : 123
     12345 : 234
   1234567 : 345
 987654321 : 654
     10001 : 000
    -10001 : 000
      -123 : 123
      -100 : 100
       100 : 100
    -12345 : 234
         1 : invalid input: too few digits
         2 : invalid input: too few digits
        -1 : invalid input: too few digits
       -10 : invalid input: too few digits
      2002 : invalid input: even number of digits
     -2002 : invalid input: even number of digits
         0 : invalid input: too few digits

[edit] BASIC

[edit] Applesoft BASIC

100 DEF FN L(N) = LEN(STR$(INT(ABS(N))))
110 DEF FN N(N) = VAL(MID$(STR$(INT(ABS(N))),(FN L(N)-1)/2,3))
120 DEF FN EVEN(N) = INT(N/2) = N/2
130 FOR I = 1 TO 20
140 READ N
150 PRINT N":",
160 GOSUB 100"MIDDLE THREE DIGITS
170 PRINT R$
180 NEXT
190 END
200 R$ = ""
210 IF FN EVEN(FN L(N)) THEN R$ = "?EVEN,"
220 IF FN L(N) < 3 THEN R$ = R$ + "ONLY " + STR$(FN L(N)) + " DIGIT" + MID$("S",FN L(N) - 1, 1)
230 IF RIGHT$(R$, 1) = "," THEN R$ = LEFT$(R$, LEN(R$) - 1) : RETURN
240 IF LEFT$(R$, 1) = "?" THEN RETURN
250 IF R$ <> "" THEN R$ = "?" + R$ : RETURN
260 R$ = STR$(FN N(N))
270 IF LEN(R$) = 1 THEN R$ = "00" + R$
280 IF LEN(R$) = 2 THEN R$ = "0" + R$
290 RETURN
300 DATA123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345
310 DATA1,2,-1,-10,2002,-2002,0
 
Output:
123:            123
12345:          234
1234567:        345
987654321:      654
10001:          000
-10001:         000
-123:           123
-100:           100
100:            100
-12345:         234
1:              ?ONLY 1 DIGIT
2:              ?ONLY 1 DIGIT
-1:             ?ONLY 1 DIGIT
-10:            ?EVEN,ONLY 2 DIGITS
2002:           ?EVEN
-2002:          ?EVEN
0:              ?ONLY 1 DIGIT

[edit] FBSL

#APPTYPE CONSOLE
 
DIM numbers AS STRING = "123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345,1,2,-1,-10,2002,-2002,0"
DIM dict[] = Split(numbers, ",")
DIM num AS INTEGER
DIM num2 AS INTEGER
DIM powered AS INTEGER
 
FOR DIM i = 0 TO COUNT(dict) - 1
num2 = dict[i]
num = ABS(num2)
IF num < 100 THEN
display(num2, "is too small")
ELSE
FOR DIM j = 9 DOWNTO 1
powered = 10 ^ j
IF num >= powered THEN
IF j MOD 2 = 1 THEN
display(num2, "has even number of digits")
ELSE
display(num2, middle3(num, j))
END IF
EXIT FOR
END IF
NEXT
END IF
NEXT
 
PAUSE
 
FUNCTION display(num, msg)
PRINT LPAD(num, 11, " "), " --> ", msg
END FUNCTION
 
FUNCTION middle3(n, pwr)
DIM power AS INTEGER = (pwr \ 2) - 1
DIM m AS INTEGER = n
m = m \ (10 ^ power)
m = m MOD 1000
IF m = 0 THEN
RETURN "000"
ELSE
RETURN m
END IF
END FUNCTION

Output

        123 --> 123
      12345 --> 234
    1234567 --> 345
  987654321 --> 654
      10001 --> 000
     -10001 --> 000
       -123 --> 123
       -100 --> 100
        100 --> 100
     -12345 --> 234
          1 --> is too small
          2 --> is too small
         -1 --> is too small
        -10 --> is too small
       2002 --> has even number of digits
      -2002 --> has even number of digits
          0 --> is too small

Press any key to continue...

[edit] PureBasic

Procedure.s middleThreeDigits(x.q)
Protected x$, digitCount
 
If x < 0: x = -x: EndIf
 
x$ = Str(x)
digitCount = Len(x$)
If digitCount < 3
ProcedureReturn "invalid input: too few digits"
ElseIf digitCount % 2 = 0
ProcedureReturn "invalid input: even number of digits"
EndIf
 
ProcedureReturn Mid(x$,digitCount / 2, 3)
EndProcedure
 
If OpenConsole()
Define testValues$ = "123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345 1 2 -1 -10 2002 -2002 0"
 
Define i, value.q, numTests = CountString(testValues$, " ") + 1
For i = 1 To numTests
value = Val(StringField(testValues$, i, " "))
PrintN(RSet(Str(value), 12, " ") + " : " + middleThreeDigits(value))
Next
 
Print(#crlf$ + #crlf$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf

Sample output:

         123 : 123
       12345 : 234
     1234567 : 345
   987654321 : 654
       10001 : 000
      -10001 : 000
        -123 : 123
        -100 : 100
         100 : 100
      -12345 : 234
           1 : invalid input: too few digits
           2 : invalid input: too few digits
          -1 : invalid input: too few digits
         -10 : invalid input: too few digits
        2002 : invalid input: even number of digits
       -2002 : invalid input: even number of digits
           0 : invalid input: too few digits

[edit] Run BASIC

x$ = "123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0"
 
while word$(x$,i+1,",") <> ""
i = i + 1
a1$ = trim$(word$(x$,i,","))
if left$(a1$,1) = "-" then a$ = mid$(a1$,2) else a$ = a1$
if (len(a$) and 1) = 0 or len(a$) < 3 then
print a1$;chr$(9);" length < 3 or is even"
else
print mid$(a$,((len(a$)-3)/2)+1,3);" ";a1$
end if
wend
end
123 123
234 12345
345 1234567
654 987654321
000 10001
000 -10001
123 -123
100 -100
100 100
234 -12345
1	 length < 3 or is even
2	 length < 3 or is even
-1	 length < 3 or is even
-10	 length < 3 or is even
2002	 length < 3 or is even
-2002	 length < 3 or is even
0	 length < 3 or is even

[edit] Bracmat

( ( middle3
= x p
. @(!arg:? [?p:? [(1/2*!p+-3/2) %?x [(1/2*!p+3/2) ?)
& !x
|  !arg
( !p:<3&"is too small"
| "has even number of digits"
)
)
& 123 12345 1234567 987654321 10001 -10001 -123 -100 100
-12345 1 2 -1 -10 2002 -2002 0
 : ?L
& whl'(!L:%?e ?L&out$(middle3$!e))
&
);
 

Output:

123
234
345
654
000
000
123
100
100
234
1 is too small
2 is too small
-1 is too small
-10 is too small
2002 has even number of digits
-2002 has even number of digits
0 is too small

[edit] C

This code is followed by its output.

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// we return a static buffer; caller wants it, caller copies it
char * mid3(int n)
{
static char buf[32];
int l;
sprintf(buf, "%d", n > 0 ? n : -n);
l = strlen(buf);
if (l < 3 || !(l & 1)) return 0;
l = l / 2 - 1;
buf[l + 3] = 0;
return buf + l;
}
 
int main(void)
{
int x[] = {123, 12345, 1234567, 987654321, 10001, -10001,
-123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0,
1234567890};
 
int i;
char *m;
for (i = 0; i < sizeof(x)/sizeof(x[0]); i++) {
if (!(m = mid3(x[i])))
m = "error";
printf("%d: %s\n", x[i], m);
}
return 0;
}
123: 123
12345: 234
1234567: 345
987654321: 654
10001: 000
-10001: 000
-123: 123
-100: 100
100: 100
-12345: 234
1: error
2: error
-1: error
-10: error
2002: error
-2002: error
0: error
1234567890: error

[edit] Alternative Version

This code has been extensively rewritten. The original was purely interactive and had to be invoked each time from the console. It also did not produce the correct answer.

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
void midThree(char arg[])
{
char output[4];
int midPoint;
arg[0]=='-'?midPoint = ((strlen(arg) + 1) / 2):midPoint = ((strlen(arg) + 1) / 2) - 1;
 
if(strlen(arg) < 3)
{
printf("Error, %d is too short.\n",atoi(arg));
return ;
}
else if(strlen(arg) == 4 || strlen(arg) == 3)
{
printf("Error, %d has %d digits, no 3 middle digits.\n",atoi(arg),arg[0]=='-'?strlen(arg)-1:strlen(arg));
return ;
}
else{
for(int i=0; i<3; i++)
{
output[i] = arg[(midPoint-1) + i];
}
output[3] = '\0';
printf("The middle three digits of %s are %s.\n",arg,output);
}}
 
int main(int argc, char * argv[])
{
char input[50];
int x[] = {123, 12345, 1234567, 987654321, 10001, -10001,
-123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0,
1234567890},i;
 
if(argc < 2)
{
printf("Usage: %s <integer>\n",argv[0]);
printf("Examples with preloaded data shown below :\n");
 
for(i=0;i<18;i++)
{
midThree(itoa(x[i],argv[0],10));
}
return 1;
}
else
{
sprintf(input,"%d",atoi(argv[1]));
midThree(argv[1]);
return 0;
 
 
}
}
Output:
Usage: C:\TurboC++\Disk\TurboC3\BIN\rosmid3_2.exe <integer>
Examples with preloaded data shown below :
Error, 123 has 3 digits, no 3 middle digits.
The middle three digits of 12345 are 234.
The middle three digits of 1234567 are 345.
The middle three digits of 987654321 are 654.
The middle three digits of 10001 are 000.
The middle three digits of -10001 are 000.
Error, -123 has 3 digits, no 3 middle digits.
Error, -100 has 3 digits, no 3 middle digits.
Error, 100 has 3 digits, no 3 middle digits.
The middle three digits of -12345 are 234.
Error, 1 is too short.
Error, 2 is too short.
Error, -1 is too short.
Error, -10 has 2 digits, no 3 middle digits.
Error, 2002 has 4 digits, no 3 middle digits.
Error, -2002 has 4 digits, no 3 middle digits.
Error, 0 is too short.
The middle three digits of 1234567890 are 456.

[edit] C#

using System;
 
namespace RosettaCode
{
class Program
{
static void Main(string[] args)
{
string text = Math.Abs(int.Parse(Console.ReadLine())).ToString();
Console.WriteLine(text.Length < 2 || text.Length % 2 == 0 ? "Error" : text.Substring((text.Length - 3) / 2, 3));
}
}
}
Output:
123:123
12345:234
1234567:345
987654321:654
10001:000
-10001:000
-123:123
-100:100
100:100
-12345:234

1:Error
2:Error
-1:Error
-10:Error
2002:Error
-2002:Error
0:Error

[edit] C++

#include <iostream>
#include <sstream>
#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;
}
 
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

[edit] Clojure

 
(defn middle3 [v]
(let [no (Math/abs v)
digits (str no)
len (count digits)]
(cond
(< len 3) :too_short
(even? len) :no_middle_in_even_no_of_digits
 :else (let [mid (/ len 2)
start (- mid 2)]
(apply str
(take 3
(nthnext digits start)))))))
 
(def passes '(123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345))
(def fails '(1 2 -1 -10 2002 -2002 0))
 
 
Output:
user=> (map middle3 passes)
("123" "234" "345" "654" "000" "000" "123" "100" "100" "234")
user=> (map middle3 fails)
(:too_short :too_short :too_short :too_short :no_middle_in_even_no_of_digits :no_middle_in_even_no_of_digits :too_short)

[edit] COBOL

identification division.
program-id. middle3.
environment division.
data division.
working-storage section.
01 num pic 9(9).
88 num-too-small values are -99 thru 99.
01 num-disp pic ---------9.
 
01 div pic 9(9).
01 mod pic 9(9).
01 mod-disp pic 9(3).
 
01 digit-counter pic 999.
01 digit-div pic 9(9).
88 no-more-digits value 0.
01 digit-mod pic 9(9).
88 is-even value 0.
 
01 multiplier pic 9(9).
 
01 value-items.
05 filler pic s9(9) value 123.
05 filler pic s9(9) value 12345.
05 filler pic s9(9) value 1234567.
05 filler pic s9(9) value 987654321.
05 filler pic s9(9) value 10001.
05 filler pic s9(9) value -10001.
05 filler pic s9(9) value -123.
05 filler pic s9(9) value -100.
05 filler pic s9(9) value 100.
05 filler pic s9(9) value -12345.
05 filler pic s9(9) value 1.
05 filler pic s9(9) value 2.
05 filler pic s9(9) value -1.
05 filler pic s9(9) value -10.
05 filler pic s9(9) value 2002.
05 filler pic s9(9) value -2002.
05 filler pic s9(9) value 0.
 
01 value-array redefines value-items.
05 items pic s9(9) occurs 17 times indexed by item.
 
01 result pic x(20).
 
procedure division.
10-main.
perform with test after varying item from 1 by 1 until items(item) = 0
move items(item) to num
move items(item) to num-disp
perform 20-check
display num-disp " --> " result
end-perform.
stop run.
 
20-check.
if num-too-small
move "Number too small" to result
exit paragraph
end-if.
 
perform 30-count-digits.
divide digit-counter by 2 giving digit-div remainder digit-mod.
if is-even
move "Even number of digits" to result
exit paragraph
end-if.
 
*> if digit-counter is 5, mul by 10
*> if digit-counter is 7, mul by 100
*> if digit-counter is 9, mul by 1000
 
if digit-counter > 3
compute multiplier rounded = 10 ** (((digit-counter - 5) / 2) + 1)
divide num by multiplier giving num
divide num by 1000 giving div remainder mod
move mod to mod-disp
else
move num to mod-disp
end-if.
move mod-disp to result.
exit paragraph.
 
30-count-digits.
move zeroes to digit-counter.
move num to digit-div.
perform with test before until no-more-digits
divide digit-div by 10 giving digit-div remainder digit-mod
add 1 to digit-counter
end-perform.
exit paragraph.

Output

       123 --> 123
     12345 --> 234
   1234567 --> 345
 987654321 --> 654
     10001 --> 000
    -10001 --> 000
      -123 --> 123
      -100 --> 100
       100 --> 100
    -12345 --> 234
         1 --> Number too small
         2 --> Number too small
        -1 --> Number too small
       -10 --> Number too small
      2002 --> Even number of digit
     -2002 --> Even number of digit
         0 --> Number too small

Optimised version

identification division.
program-id. middle3.
environment division.
data division.
working-storage section.
01 value-items.
05 filler pic s9(9) value 123.
05 filler pic s9(9) value 12345.
05 filler pic s9(9) value 1234567.
05 filler pic s9(9) value 987654321.
05 filler pic s9(9) value 10001.
05 filler pic s9(9) value -10001.
05 filler pic s9(9) value -123.
05 filler pic s9(9) value -100.
05 filler pic s9(9) value 100.
05 filler pic s9(9) value -12345.
05 filler pic s9(9) value 1.
05 filler pic s9(9) value 2.
05 filler pic s9(9) value -1.
05 filler pic s9(9) value -10.
05 filler pic s9(9) value 2002.
05 filler pic s9(9) value -2002.
05 filler pic s9(9) value 0.
 
01 value-array redefines value-items.
05 items pic s9(9) occurs 17 times indexed by item.
 
01 num pic 9(9).
01 num-disp pic ---------9.
01 num2 pic 9(9).
 
01 power pic 9.
01 power10 pic 9(16).
 
01 three-digits pic 999.
 
01 result pic X(20).
 
01 flag pic 9.
88 done value 1.
 
procedure division.
01-setup.
perform 02-outer with test after varying item from 1 by 1 until items(item) = 0.
stop run.
 
02-outer.
move items(item) to num.
move items(item) to num-disp.
if num less than 100
move "too small" to result
else
perform 03-inner with test after varying power from 9 by -1 until power = 1 or done
end-if.
display num-disp " --> " result.
exit paragraph.
 
03-inner.
move 0 to flag.
compute power10 = 10 ** power.
if num >= power10
move 1 to flag
if function mod(power,2) = 1
move "even number digits" to result
else
move num to num2
compute num2 = num2 / ( 10 ** (( power / 2 ) - 1 ))
move function mod(num2,1000) to three-digits
move three-digits to result
end-if
end-if.
 
 

Output

       123 --> 123
     12345 --> 234
   1234567 --> 345
 987654321 --> 654
     10001 --> 000
    -10001 --> 000
      -123 --> 123
      -100 --> 100
       100 --> 100
    -12345 --> 234
         1 --> too small
         2 --> too small
        -1 --> too small
       -10 --> too small
      2002 --> even number digits
     -2002 --> even number digits
         0 --> too small

[edit] Common Lisp

 
(defun mid3 (n)
(let ((a (abs n))
(hmd)) ; how many digits
(labels ((give (fmt &optional x y) (return-from mid3 (format nil fmt x y)))
(need (x) (give "Need ~a digits, not ~d." x hmd))
(nbr (n) (give "~3,'0d" n)))
(when (zerop n) (give "Zero is 1 digit"))
(setq hmd (truncate (1+ (log a 10))))
(cond ((< hmd 3) (need "3+"))
((= hmd 3) (nbr a))
((evenp hmd) (need "odd number of"))
(t (nbr (mod (truncate a (expt 10 (/ (- hmd 3) 2))) 1000)))))))
 

Test code:

 
(loop as n in '(123 12345 1234567 987654321
10001 -10001 -123 -100 100 -12345
1 2 -1 -10 2002 -2002 0)
do (format t "~d:~12t~a~%" n (mid3 n)))
 
Output:
123:        123
12345:      234
1234567:    345
987654321:  654
10001:      000
-10001:     000
-123:       123
-100:       100
100:        100
-12345:     234
1:          Need 3+ digits, not 1.
2:          Need 3+ digits, not 1.
-1:         Need 3+ digits, not 1.
-10:        Need 3+ digits, not 2.
2002:       Need odd number of digits, not 4.
-2002:      Need odd number of digits, not 4.
0:          Zero is 1 digit

[edit] D

import std.stdio, std.traits, std.conv;
 
string middleThreeDigits(T)(in T n) pure nothrow 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 (immutable n; passing)
writefln("middleThreeDigits(%s): %s", n, middleThreeDigits(n));
 
immutable failing = [1, 2, -1, -10, 2002, -2002, 0,int.min,int.max];
foreach (immutable n; failing)
writefln("middleThreeDigits(%s): %s", n, middleThreeDigits(n));
}
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

[edit] Alternative Version

This longer version gives a stronger typed output, and it tries to be faster avoiding conversions to string.

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);
}
}
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

[edit] Erlang

% 
-module(middle_three_digits).
-export([main/0]).
 
main() ->
digits(123),
digits(12345),
digits(1234567),
digits(987654321),
digits(10001),
digits(-10001),
digits(-123),
digits(-100),
digits(100),
digits(-12345),
digits(1),
digits(2),
digits(-1),
digits(-10),
digits(2002),
digits(-2002),
digits(0).
 
digits(N) when N < 0 ->
digits(-N);
digits(N) when (N div 100) =:= 0 ->
io:format("too small\n");
digits(N) ->
K=length(integer_to_list(N)),
if (K rem 2) =:= 0 ->
io:format("even number of digits\n");
true ->
loop((K-3) div 2 , N)
end.
 
loop(0, N) ->
io:format("~3..0B~n",[N rem 1000]);
loop(X,N) when X>0 ->
loop(X-1, N div 10).
 
Output:
123
234
345
654
000
000
123
100
100
234
too small
too small
too small
too small
even number of digits
even number of digits
too small
ok

[edit] Forth

This is a problem, which is easily solved in Forth. It converts the number to a string and checks it length. If the number does not represent a printable string, it returns an empty string.

: middle3          ( n1 -- a n2)
abs s>d <# #s #> dup 2/ 0<> over 1 and 0<> and
if 2/ 1- chars + 3 else drop 0 then
;

[edit] Fortran

Please find compilation instructions along with the output for the examples in the comments at the beginning of the file. This program was produced in an Ubuntu distribution of the GNU/linux system.

 
!-*- mode: compilation; default-directory: "/tmp/" -*-
!Compilation started at Sat Jun 1 14:48:41
!
!a=./f && make $a && OMP_NUM_THREADS=2 $a < unixdict.txt # some of the compilation options and redirection from unixdict.txt are vestigial.
!gfortran -std=f2008 -Wall -fopenmp -ffree-form -fall-intrinsics -fimplicit-none f.f08 -o f
! 123 123
! 12345 234
! 1234567 345
! 987654321 654
! 10001 000
! -10001 000
! -123 123
! -100 100
! 100 100
! -12345 234
! 1 Too short
! 2 Too short
! -1 Too short
! -10 Too short
! 2002 Digit count too even
! -2002 Digit count too even
! 0 Too short
!
!Compilation finished at Sat Jun 1 14:48:41
 
 
program MiddleMuddle
integer, dimension(17) :: itest, idigits
integer :: i, n
data itest/123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345,1,2,-1,-10,2002,-2002,0/
do i = 1, size(itest)
call antibase(10, abs(itest(i)), idigits, n)
write(6,'(i20,2x,a20)') itest(i), classifym3(idigits, n)
if (0 .eq. itest(i)) exit
end do
 
contains
 
logical function even(n)
integer, intent(in) :: n
even = 0 .eq. iand(n,1)
end function even
 
function classifym3(iarray, n) result(s)
integer, dimension(:), intent(in) :: iarray
integer, intent(in) :: n
character(len=20) :: s
integer :: i,m
if (n < 3) then
s = 'Too short'
else if (even(n)) then
s = 'Digit count too even'
else
m = (n+1)/2
write(s,'(3i1)')(iarray(i), i=m+1,m-1,-1)
end if
end function classifym3
 
subroutine antibase(base, m, digits, n) ! digits ordered by increasing significance
integer, intent(in) :: base, m
integer, intent(out) :: n ! the number of digits
integer, dimension(:), intent(out) :: digits
integer :: em
em = m
do n=1, size(digits)
digits(n) = mod(em, base)
em = em / base
if (0 .eq. em) return
end do
stop 'antibase ran out of space to store result'
end subroutine antibase
 
end program MiddleMuddle
 

[edit] Go

Unlike most Go examples on RC, this is written as a package to show operation of the go test tool.

File m3.go:

package m3
 
import (
"errors"
"strconv"
)
 
var (
ErrorLT3 = errors.New("N of at least three digits required.")
ErrorEven = errors.New("N with odd number of digits required.")
)
 
func Digits(i int) (string, error) {
if i < 0 {
i = -i
}
if i < 100 {
return "", ErrorLT3
}
s := strconv.Itoa(i)
if len(s)%2 == 0 {
return "", ErrorEven
}
m := len(s) / 2
return s[m-1 : m+2], nil
}

File m3_test.go:

package m3_test
 
import (
"testing"
 
"m3"
)
 
func TestPassing(t *testing.T) {
type s struct {
i int
m string
}
tcs := []s{
{123, "123"},
{12345, "234"},
{1234567, "345"},
{987654321, "654"},
{10001, "000"},
{-10001, "000"},
}
for _, tc := range tcs {
m, err := m3.Digits(tc.i)
if err != nil {
t.Fatalf("d(%d) returned %q.", tc.i, err)
}
if m != tc.m {
t.Fatalf("d(%d) expected %q, got %q.", tc.i, tc.m, m)
}
t.Logf("d(%d) = %q.", tc.i, m)
}
}
 
func TestFailing(t *testing.T) {
type s struct {
i int
err error
}
tcs := []s{
{1, m3.ErrorLT3},
{2, m3.ErrorLT3},
{-1, m3.ErrorLT3},
{-10, m3.ErrorLT3},
{2002, m3.ErrorEven},
{-2002, m3.ErrorEven},
{0, m3.ErrorLT3},
}
for _, tc := range tcs {
m, err := m3.Digits(tc.i)
if err == nil {
t.Fatal("d(%d) expected error %q, got non-error %q.",
tc.i, tc.err, m)
}
if err != tc.err {
t.Fatal("d(d) expected error %q, got %q", tc.i, tc.err, err)
}
t.Logf("d(%d) returns %q", tc.i, err)
}
}
Output:

Output of go test is normally terse:

> go test
PASS
ok      m3      0.008s

With -v (for verbose):

> go test -v
=== RUN TestPassing-4
--- PASS: TestPassing-4 (0.00 seconds)
        m3_test.go:30: d(123) = "123".
        m3_test.go:30: d(12345) = "234".
        m3_test.go:30: d(1234567) = "345".
        m3_test.go:30: d(987654321) = "654".
        m3_test.go:30: d(10001) = "000".
        m3_test.go:30: d(-10001) = "000".
=== RUN TestFailing-4
--- PASS: TestFailing-4 (0.00 seconds)
        m3_test.go:57: d(1) returns "N of at least three digits required."
        m3_test.go:57: d(2) returns "N of at least three digits required."
        m3_test.go:57: d(-1) returns "N of at least three digits required."
        m3_test.go:57: d(-10) returns "N of at least three digits required."
        m3_test.go:57: d(2002) returns "N with odd number of digits required."
        m3_test.go:57: d(-2002) returns "N with odd number of digits required."
        m3_test.go:57: d(0) returns "N of at least three digits required."
PASS
ok      m3      0.008s

[edit] Groovy

def middleThree(Number number) {
def text = Math.abs(number) as String
assert text.size() >= 3 : "'$number' must be more than 3 numeric digits"
assert text.size() % 2 == 1 : "'$number' must have an odd number of digits"
 
int start = text.size() / 2 - 1
text[start..(start+2)]
}

Test Code:

[123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0].each { number ->
def text = (number as String).padLeft(10)
try {
println "$text: ${middleThree(number)}"
} catch(AssertionError error) {
println "$text cannot be converted: $error.message"
}
}

Output:

       123: 123
     12345: 234
   1234567: 345
 987654321: 654
     10001: 000
    -10001: 000
      -123: 123
      -100: 100
       100: 100
    -12345: 234
         1 cannot be converted: '1' must be more than 3 numeric digits. Expression: (text.size() >= 3)
         2 cannot be converted: '2' must be more than 3 numeric digits. Expression: (text.size() >= 3)
        -1 cannot be converted: '-1' must be more than 3 numeric digits. Expression: (text.size() >= 3)
       -10 cannot be converted: '-10' must be more than 3 numeric digits. Expression: (text.size() >= 3)
      2002 cannot be converted: '2002' must have an odd number of digits. Expression: ((text.size() % 2) == 1)
     -2002 cannot be converted: '-2002' must have an odd number of digits. Expression: ((text.size() % 2) == 1)
         0 cannot be converted: '0' must be more than 3 numeric digits. Expression: (text.size() >= 3)

[edit] Haskell

import Numeric
 
mid3 :: Integral a => a -> Either String String
mid3 n | m < 100 = Left "is too small"
| even l = Left "has an even number of digits"
| otherwise = Right . take 3 $ drop ((l-3) `div` 2) s
where m = abs n
s = showInt m ""
l = length s
 
showMid3 :: Integer -> String
showMid3 n = show n ++ ": " ++ either id id (mid3 n)
 
main :: IO ()
main = mapM_ (putStrLn . showMid3) [
123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345,
1, 2, -1, -10, 2002, -2002, 0]

Output:

123: 123
12345: 234
1234567: 345
987654321: 654
10001: 000
-10001: 000
-123: 123
-100: 100
100: 100
-12345: 234
1: is too small
2: is too small
-1: is too small
-10: is too small
2002: has an even number of digits
-2002: has an even number of digits
0: is too small

[edit] Icon and Unicon

The following solution works in both languages.

procedure main(a)
every n := !a do write(right(n,15)," -> ",midM(n))
end
 
procedure midM(n,m)
/m := 3
n := abs(n)
return n ? if (*n >= m) then
if (((*n-m) % 2) = 0) then (move((*n - m)/2),move(m))
else "wrong number of digits"
else "too short"
end

with output:

->m3d 123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345 1 2 -1 -10 2002 -2002 0
            123 -> 123
          12345 -> 234
        1234567 -> 345
      987654321 -> 654
          10001 -> 000
         -10001 -> 000
           -123 -> 123
           -100 -> 100
            100 -> 100
         -12345 -> 234
              1 -> too short
              2 -> too short
             -1 -> too short
            -10 -> too short
           2002 -> wrong number of digits
          -2002 -> wrong number of digits
              0 -> too short
->

[edit] J

Solution:

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@:|

Example:

   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

[edit] 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);
}
}
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

[edit] JavaScript

function middleThree(x){
var n=''+Math.abs(x); var l=n.length-1;
if(l<2||l%2) throw new Error(x+': Invalid length '+(l+1));
return n.slice(l/2-1,l/2+2);
}
 
[123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345,
1, 2, -1, -10, 2002, -2002, 0].forEach(function(n){
try{console.log(n,middleThree(n))}catch(e){console.error(e.message)}
});
123 "123"
12345 "234"
1234567 "345"
987654321 "654"
10001 "000"
-10001 "000"
-123 "123"
-100 "100"
100 "100"
-12345 "234"
1: Invalid length 1
2: Invalid length 1
-1: Invalid length 1
-10: Invalid length 2
2002: Invalid length 4
-2002: Invalid length 4
0: Invalid length 1

[edit] jq

def middle3:
if . < 0 then -. else . end
| tostring as $s
| ($s | length) as $n
| if $n<3 or ($n % 2) == 0 then "invalid length: \($n)"
else (($n - 1) / 2) as $n | $s[$n - 1 : $n + 2]
end ;
 
(123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0)
| "\(.) => \( .|middle3 )"
Typescript:
 $ jq -r -n -f Middle_three_digits.jq
123 => 123
12345 => 234
1234567 => 345
987654321 => 654
10001 => 000
-10001 => 000
-123 => 123
-100 => 100
100 => 100
-12345 => 234
1 => invalid length: 1
2 => invalid length: 1
-1 => invalid length: 1
-10 => invalid length: 2
2002 => invalid length: 4
-2002 => invalid length: 4
0 => invalid length: 1

[edit] Julia

function middle(i)
s = string(abs(i))
l = length(s)
mid = int((l+1)/2)
l < 3 ?
"error: not enough digits"  :
iseven(l) ?
"error: number of digits is even"  :
join((s[mid-1],s[mid],s[mid+1]))
end
 
function dummy(x,y,z=5)
"""
A dummy docstring over two lines
for text coloration.
"""
print("this is just some text to show text", 1.0, 3)
# and comment coloration
// and comment coloration 2
end
 
julia>
 
for n = [123, 12345, 1234567, 987654321, 10001, -10001, -123,
-100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0]
println (@sprintf("%10d : ", n), middle(n))
end

Output

       123 : 123
     12345 : 234
   1234567 : 345
 987654321 : 654
     10001 : 000
    -10001 : 000
      -123 : 123
      -100 : 100
       100 : 100
    -12345 : 234
         1 : error: not enough digits
         2 : error: not enough digits
        -1 : error: not enough digits
       -10 : error: not enough digits
      2002 : error: number of digits is even
     -2002 : error: number of digits is even
         0 : error: not enough digits

[edit] Lasso

define middlethree(value::integer) => {
local(
pos_value = math_abs(#value),
stringvalue = #pos_value -> asstring,
intlength = #stringvalue -> size,
middle = integer((#intlength + 1) / 2),
prefix = string(#value) -> padleading(15)& + ': '
)
 
#intlength < 3 ? return #prefix + 'Error: too few digits'
not(#intlength % 2) ? return #prefix + 'Error: even number of digits'
 
return #prefix + #stringvalue -> sub(#middle -1, 3)
 
}
'<pre>'
with number in array(123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0) do {^
 
middlethree(#number)
'<br />'
^}
'</pre>'

Output

            123: 123
          12345: 234
        1234567: 345
      987654321: 654
          10001: 000
         -10001: 000
           -123: 123
           -100: 100
            100: 100
         -12345: 234
              1: Error: too few digits
              2: Error: too few digits
             -1: Error: too few digits
            -10: Error: too few digits
           2002: Error: even number of digits
          -2002: Error: even number of digits
              0: Error: too few digits

[edit] Lua

function middle_three(n)
if n < 0 then
n = -n
end
 
n = tostring(n)
if #n % 2 == 0 then
return "Error: the number of digits is even."
elseif #n < 3 then
return "Error: the number has less than 3 digits."
end
 
local l = math.floor(#n/2)
return n:sub(l, l+2)
end
 
-- test
do
local t = {123, 12345, 1234567, 987654321,
10001, -10001, -123, -100, 100, -12345, 1,
2, -1, -10, 2002, -2002, 0}
 
for _,n in pairs(t) do
print(n, middle_three(n))
end
end
Output:
123	123
12345	234
1234567	345
987654321	654
10001	000
-10001	000
-123	123
-100	100
100	100
-12345	234
1	Error: the number has less than 3 digits.
2	Error: the number has less than 3 digits.
-1	Error: the number has less than 3 digits.
-10	Error: the number is even.
2002	Error: the number is even.
-2002	Error: the number is even.
0	Error: the number has less than 3 digits.

[edit] Mathematica

middleThree[n_Integer] :=
Block[{digits = IntegerDigits[n], len},
len = Length[digits];
If[len < 3 || EvenQ[len], "number digits odd or less than 3",
len = Ceiling[len/2];
StringJoin @@ (ToString /@ digits[[len - 1 ;; len + 1]])]]
 
testData = {123, 12345, 1234567, 987654321, 10001, -10001, -123, -100,
100, -12345, 1, 2, -1, -10, 2002, -2002, 0};
 
Column[middleThree /@ testData]
Output:

123 234 345 654 000 000 123 100 100 234 err: n too small err: n too small err: n too small err: n too small err: even number of digits err: even number of digits err: n too small

[edit] MATLAB / Octave

function s=middle_three_digits(a)
% http://rosettacode.org/wiki/Middle_three_digits
 
s=num2str(abs(a));
 
if ~mod(length(s),2)
s='*** error: number of digits must be odd ***';
return;
end;
if length(s)<3,
s='*** error: number of digits must not be smaller than 3 ***';
return;
end;
 
s = s((length(s)+1)/2+[-1:1]);

Test with

 x=[123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0];
for k=1:length(x); fprintf(1,'%9i:%s\n',x(k),middle_three_digits(x(k)));end;

Result

      123:123
    12345:234
  1234567:457
987654321:654
    10001:000
   -10001:000
     -123:123
     -100:100
      100:100
   -12345:234
        1:*** error: number of digits must not be smaller than 3 ***
        2:*** error: number of digits must not be smaller than 3 ***
       -1:*** error: number of digits must not be smaller than 3 ***
      -10:*** error: number of digits must be odd ***
     2002:*** error: number of digits must be odd ***
    -2002:*** error: number of digits must be odd ***
        0:*** error: number of digits must not be smaller than 3 ***

[edit] МК-61/52

П0	lg	[x]	3	-	x>=0	23	ИП0	1	0
/ [x] ^ lg [x] 10^x П1 / {x} ИП1
* БП 00 1 + x=0 29 ИП0 С/П 0
/

Instruction: enter the number in the РX (on display), the result after the execution of the same. In the case of an even or less than 3 number of digits the indicator displays an error message.

[edit] ML

[edit] mLite

This example is incorrect. It does not accomplish the given task. Please fix the code and remove this message.
This example is incorrect. The output does not show the original input. Please fix the code and remove this message.
 
val test_array = ["123","12345","1234567","987654321","10001","~10001","~123","~100","100","~12345","1","2","~1","~10","2002","~2002","0"];
 
fun even (x rem 2 = 0) = true | _ = false;
 
fun middleThreeDigits
(h :: t, s, 1 ) = s @ " --> too small"
| (h :: t, s, 2 ) = s @ " --> has even digits"
| (h :: t, s, 3 ) where (len (h :: t) = 3) = s @ " --> " @ (implode (h :: t))
| (h :: t, s, 3 ) = (middleThreeDigits ( sub (t, 0, (len t)-1), s, 3))
| (h :: t, s, m) = if len (h :: t) < 3 then
middleThreeDigits (h :: t, s, 1)
else
if even ` len (h :: t) then
middleThreeDigits (h :: t, s, 2)
else
middleThreeDigits (h :: t, s, 3)
 
 
| s = if sub (s, 0, 1) = "~" then
middleThreeDigits (sub (explode s, 1, len s), s, 0)
else
middleThreeDigits (explode s, s, 0)
;
 
map (println o middleThreeDigits) test_array;

Output:

123 --> 123
12345 --> 234
1234567 --> 345
987654321 --> 654
10001 --> 000
~10001 --> 000
~123 --> 123
~100 --> 100
100 --> 100
~12345 --> 234
1 --> too small
2 --> too small
~1 --> too small
~10 --> too small
2002 --> has even digits
~2002 --> has even digits
0 --> too small

[edit] NetRexx

This sample goes the extra mile and provides a method that can display the middle N digits from the input value. To satisfy the requirements of this task, a static invocation of this general method is also provided with the value 3 hard coded as the digit count.

/* 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 middle3Digits(val) constant
return middleDigits(3, val)
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method middleDigits(digitCt, val) constant
text = val.right(15)':'
even = digitCt // 2 == 0 -- odd or even?
select
when digitCt <= 0 then text = 'digit selection size must be >= 1'
when \val.datatype('w') then text = text 'is not a whole number'
when val.abs().length < digitCt then text = text 'has less than' digitCt '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 - digitCt) % 2
text = text val.substr(cutP + 1, digitCt)
end
catch NumberFormatException
text = val 'is not numeric'
end
return text
 

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

[edit] Nimrod

import math
 
proc middleThreeDigits(i): auto =
var s = $abs(i)
if s.len < 3 or s.len mod 2 == 0:
raise newException(EInvalidValue, "Need odd and >= 3 digits")
let mid = s.len div 2
return s[mid-1..mid+1]
 
const passing = @[123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345]
const failing = @[1, 2, -1, -10, 2002, -2002, 0]
 
for i in passing & failing:
var answer = try: middleThreeDigits(i)
except EInvalidValue: getCurrentExceptionMsg()
echo "middleThreeDigits(",i,") returned: ",answer

Output:

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

[edit] 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;
;;
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

[edit] PARI/GP

Works with: PARI/GP version 2.6.0
middle(n)=my(v=digits(n));if(#v>2&&#v%2,100*v[#v\2]+10*v[#v\2+1]+v[#v\2+2],"no middle 3 digits");
apply(middle,[123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0])

Output:

%1 = [123, 234, 345, 654, 0, 0, 123, 100, 100, 234, "no middle 3 digits", "no middle 3 digits", "no middle 3 digits", "no middle 3 digits", "no middle 3 digits", "no middle 3 digits", "no middle 3 digits"]

If for some reason you want to see the leading digits, you can run

apply(n-> Strprintf("%03d", n), %)

For earlier versions digits can be defined as

digits(n)=eval(Vec(Str(n)))

or more efficiently as

digits(n)=Vec(apply(n->n-48,Vectorsmall(Str(n))))

[edit] 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 ;
 
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!

[edit] Perl 6

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
>;
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

[edit] PHP

// 32-bit builds of PHP: Integers can be from -2147483648 to 2147483647
// 64-bit builds of PHP: Integers can be from -9223372036854775808 to 9223372036854775807
 
function middlethree($integer)
{
$int = (int)str_replace('-','',$integer);
$length = strlen($int);
 
if(is_int($int))
{
if($length >= 3)
{
if($length % 2 == 1)
{
$middle = floor($length / 2) - 1;
return substr($int,$middle, 3);
}
else
{
return 'The value must contain an odd amount of digits...';
}
}
else
{
return 'The value must contain at least three digits...';
}
}
else
{
return 'The value does not appear to be an integer...';
}
}
 
$numbers = array(123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0);
 
foreach($numbers as $nums)
{
echo $nums.' : '.middlethree($nums). '<br>';
}

Output:

123 : 123
12345 : 234
1234567 : 345
987654321 : 654
10001 : 000
-10001 : 000
-123 : 123
-100 : 100
100 : 100
-12345 : 234
1 : The value must contain at least three digits...
2 : The value must contain at least three digits...
-1 : The value must contain at least three digits...
-10 : The value must contain at least three digits...
2002 : The value must contain an odd amount of digits...
-2002 : The value must contain an odd amount of digits...
0 : The value must contain at least three digits...

[edit] PicoLisp

(de middle3digits (N)
(let (Lst (chop (abs N)) Len (length Lst))
(tab (10 -2 -30)
N
":"
(cond
((> 3 Len) "not enough digits")
((bit? 1 Len)
(head 3 (nth Lst (/ Len 2))) )
(T "even number of digits") ) ) ) )

Test:

(mapc middle3digits
(123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345
1 2 -1 -10 2002 -2002 0 ) )

Output:

       123: 123
     12345: 234
   1234567: 345
 987654321: 654
     10001: 000
    -10001: 000
      -123: 123
      -100: 100
       100: 100
    -12345: 234
         1: not enough digits
         2: not enough digits
        -1: not enough digits
       -10: not enough digits
      2002: even number of digits
     -2002: even number of digits
         0: not enough digits

[edit] PL/I

 
middle: procedure options (main); /* 29 October 2013 */
declare n fixed (15);
declare s character (25) varying;
declare in file input;
 
open file (in) title ('/MIDDLE.DAT,type(text),recsize(100)');
on endfile (in) stop;
 
do forever;
get file (in) list (n); put skip list (n);
n = abs(n);
s = trim(n);
if length(s) < 3 then put list ('not possible');
else if mod(length(s), 2) = 0 then put list ('not possible');
else
do;
do while (length(s) > 3);
s = substr(s, 2, length(s)-2);
end;
put list ('The middle three digits are: ' || s);
end;
end;
 
end middle;
 

Output:

               123      The middle three digits are: 123 
             12345      The middle three digits are: 234 
           1234567      The middle three digits are: 345 
         987654321      The middle three digits are: 654 
             10001      The middle three digits are: 000 
            -10001      The middle three digits are: 000 
              -123      The middle three digits are: 123 
              -100      The middle three digits are: 100 
               100      The middle three digits are: 100 
           -123451      not possible 
                 2      not possible 
                -1      not possible 
               -10      not possible 
              2002      not possible 
             -2002      not possible 
                 0      not possible

[edit] Prolog

Works with: SWI-Prolog version 6
 
middle_3_digits(Number, [D1,D2,D3]) :-
verify_middle_3_able(Number, Digits),
append(FrontDigits, [D1,D2,D3| BackDigits], Digits),
same_length(FrontDigits, BackDigits).
 
verify_middle_3_able(Number, Digits) :-
must_be(number, Number),
AbsNumber is abs(Number),
number_chars(AbsNumber, Digits),
length(Digits, NumDigits),
( 3 > NumDigits -> domain_error('at least 3 digits', Number)
; 0 is NumDigits mod 2 -> domain_error('odd number of digits', Number)
; true
).
 


Test code:

 
test_correct :-
TestCases = [123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345],
foreach( ( member(TestCase, TestCases),
middle_3_digits(TestCase, Result) ),
format('Middle 3 digits of ~w ~30|: ~w~n', [TestCase, Result])
).
 


Testing correct inputs:

?- test_correct.
Middle 3 digits of 123        : [1,2,3]
Middle 3 digits of 12345      : [2,3,4]
Middle 3 digits of 1234567    : [3,4,5]
Middle 3 digits of 987654321  : [6,5,4]
Middle 3 digits of 10001      : [0,0,0]
Middle 3 digits of -10001     : [0,0,0]
Middle 3 digits of -123       : [1,2,3]
Middle 3 digits of -100       : [1,0,0]
Middle 3 digits of 100        : [1,0,0]
Middle 3 digits of -12345     : [2,3,4]
true.

Errors

?- middle_3_digits(1, S).
ERROR: Domain error: `at least 3 digits' expected, found `1'
?- middle_3_digits(2, S).
ERROR: Domain error: `at least 3 digits' expected, found `2'
?- middle_3_digits(-1, S).
ERROR: Domain error: `at least 3 digits' expected, found `-1'
?- middle_3_digits(-10, S).
ERROR: Domain error: `at least 3 digits' expected, found `-10'
?- middle_3_digits(2002, S).
ERROR: Domain error: `odd number of digits' expected, found `2002'
?- middle_3_digits(-2002, S).
ERROR: Domain error: `odd number of digits' expected, found `-2002'
?- middle_3_digits(0, S).
ERROR: Domain error: `at least 3 digits' expected, found `0'

[edit] 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',)
>>>

[edit] Racket

#lang racket
(define (middle x)
(cond
[(negative? x) (middle (- x))]
[(< x 100) "error: number too small"]
[else
(define s (number->string x))
(define l (string-length s))
(cond [(even? l) "error: number has even length"]
[else (define i (quotient l 2))
(substring s (- i 1) (+ i 2))])]))
 
(map middle (list 123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345))
(map middle (list 1 2 -1 -10 2002 -2002 0))

The output:

'("123" "234" "345" "654" "000" "000" "123" "100" "100" "234")
'("error: number too small" "error: number too small" "error: number too small" "error: number too small"
"error: number has even length" "error: number has even length" "error: number too small")

[edit] REXX

[edit] version 1

/* REXX ***************************************************************
* 03.02.2013 Walter Pachl
* 19.04.2013 mid 3 is now a function returning the middle 3 digits
* or an error indication
**********************************************************************/

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 */
Say left(s,12) '->' 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 Return 'not a number'
When pos('E',translate(d))>0 Then Return 'not just digits'
When length(abs(d))<3 Then Return 'less than 3 digits'
When length(abs(d))//2<>1 Then Return '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 */
res=substr(dx,z+1,3) /* get middle 3 digits */
End
End
Return res

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

[edit] version 2

A premise:   12.3e2   is an integer   (regardless of how it's displayed).
So is the value of a   googol   and a  googleplex.

This REXX version is limited to numbers whose absolute value ≤ 100,000 digits.
(The limit is defined via the   NUMERIC DIGITS   statement.)

/*REXX program returns the 3 middle digits of a number  (or an error).  */
n ='123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345',
'2 -1 -10 2002 -2002 0 abc 1e3 -17e-3 1234567. 1237654.00',
'1234567890123456789012345678901234567890123456789012345678901234567'
 
do j=1 for words(n); z=word(n,j) /* [↓] format the output nicely.*/
say 'middle 3 digits of' right(z,max(15,length(z))) '──►' middle3(z)
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────MIDDLE3 subroutine──────────────────*/
middle3: procedure; arg x; numeric digits 1e5; er=' ***error!*** '
if datatype(x,'N') then x=abs(x); L=length(x)
if \datatype(x,'W') then return er "arg isn't an integer"
if L<3 then return er "arg is less than three digits"
if L//2==0 then return er "arg isn't an odd number of digits"
return substr(x, (L-3)%2+1, 3)

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 of               2 ──►     ***error!***  arg is less then three digits
middle 3 digits of              -1 ──►     ***error!***  arg is less then three digits
middle 3 digits of             -10 ──►     ***error!***  arg is less then three digits
middle 3 digits of            2002 ──►     ***error!***  arg isn't an odd number of digits
middle 3 digits of           -2002 ──►     ***error!***  arg isn't an odd number of digits
middle 3 digits of               0 ──►     ***error!***  arg is less then three digits
middle 3 digits of             abc ──►     ***error!***  arg isn't an integer
middle 3 digits of             1e3 ──►     ***error!***  arg isn't an odd number of digits
middle 3 digits of          -17e-3 ──►     ***error!***  arg isn't an integer
middle 3 digits of        1234567. ──► 345
middle 3 digits of      1237654.00 ──► 376
middle 3 digits of 1234567890123456789012345678901234567890123456789012345678901234567 ──► 345

[edit] Ruby

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

Testing program:

samples = [ 
123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345,
1, 2, -1, -10, 2002, -2002, 0
]
 
left_column_width = samples.map { |n| n.to_s.length }.max
samples.each do |n|
print "%#{left_column_width}d: " % n
begin
puts "%03d" % middle_three_digits(n)
rescue ArgumentError => e
puts e
end
end
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

[edit] Rust

// rust 0.8
 
fn middle_three_digits(x: int) -> Result<~str, ~str> {
let s = x.abs().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).to_owned())
}
}
 
fn print_result(x: int) {
print!("middle_three_digits({}) returned: ", x);
match middle_three_digits(x) {
Ok(s) => println!("Success, {}", s),
Err(s) => println!("Failure, {}", 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 i in passing.iter() {
print_result(*i);
}
for i in failing.iter() {
print_result(*i);
}
}
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

[edit] 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")
 
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

[edit] Seed7

$include "seed7_05.s7i";
 
const func string: middle3 (in integer: number) is func
result
var string: middle3 is "";
begin
middle3 := str(abs(number));
if not odd(length(middle3)) or length(middle3) < 3 then
middle3 := "error";
else
middle3 := middle3[succ((length(middle3) - 3) div 2) len 3];
end if;
end func;
 
const proc: main is func
local
var integer: number is 0;
var string: mid3 is "";
begin
for number range [] (123, 12345, 1234567, 987654321, 10001, -10001, -123,
-100, 100, -12345, 1, 2, -1, -10, 2002, -2002, 0) do
writeln(number <& ": " <& middle3(number));
end for;
end func;
Output:
123: 123
12345: 234
1234567: 345
987654321: 654
10001: 000
-10001: 000
-123: 123
-100: 100
100: 100
-12345: 234
1: error
2: error
-1: error
-10: error
2002: error
-2002: error
0: error

[edit] SQL

;WITH DATA 
AS (SELECT CAST(ABS(NUMBER) AS NVARCHAR(MAX)) charNum,
NUMBER,
LEN(CAST(ABS(NUMBER) AS NVARCHAR(MAX))) LcharNum
FROM TABLE1)
SELECT CASE
WHEN ( LCHARNUM >= 3
AND LCHARNUM % 2 = 1 ) THEN SUBSTRING(CHARNUM, LCHARNUM / 2, 3)
ELSE 'Error!'
END Output,
NUMBER INPUT
FROM DATA
| OUTPUT |     INPUT |
|--------|-----------|
|    123 |       123 |
|    234 |     12345 |
|    345 |   1234567 |
|    654 | 987654321 |
|    000 |     10001 |
|    000 |    -10001 |
|    123 |      -123 |
|    100 |      -100 |
|    100 |       100 |
|    234 |    -12345 |
| OUTPUT | INPUT |
|--------|-------|
| Error! |     1 |
| Error! |     2 |
| Error! |    -1 |
| Error! |   -10 |
| Error! |  2002 |
| Error! | -2002 |
| Error! |     0 |
		

[edit] Tcl

proc middleThree n {
if {$n < 0} {
set n [expr {-$n}]
}
set idx [expr {[string length $n] - 2}]
if {$idx % 2 == 0} {
error "no middle three digits: input is of even length"
}
if {$idx < 1} {
error "no middle three digits: insufficient digits"
}
set idx [expr {$idx / 2}]
string range $n $idx [expr {$idx+2}]
}

Demonstrating:

foreach n {
123 12345 1234567 987654321 10001 -10001 -123 -100 100 -12345
1 2 -1 -10 2002 -2002 0
} {
if {[catch {
set mid [middleThree $n]
} msg]} then {
puts "error for ${n}: $msg"
} else {
puts "found for ${n}: $mid"
}
}
Output:
found for 123: 123
found for 12345: 234
found for 1234567: 345
found for 987654321: 654
found for 10001: 000
found for -10001: 000
found for -123: 123
found for -100: 100
found for 100: 100
found for -12345: 234
error for 1: no middle three digits: insufficient digits
error for 2: no middle three digits: insufficient digits
error for -1: no middle three digits: insufficient digits
error for -10: no middle three digits: input is of even length
error for 2002: no middle three digits: input is of even length
error for -2002: no middle three digits: input is of even length
error for 0: no middle three digits: insufficient digits

[edit] UNIX Shell

Works with: Bourne Again Shell
Works with: Korn Shell version 93
Works with: Z Shell
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
}
 
# 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
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

[edit] Vedit macro language

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
#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

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! 

[edit] Wart

def (mid3 n)
withs (digits (with outstring # itoa
(pr abs.n))
max len.digits
mid (int max/2))
if (and odd?.max (max >= 3))
(digits mid-1 mid+2)

Output

mid3.123
=> 123
mid3.12345
=> 234
mid3.1234567
=> 345
mid3.987654321
=> 654
mid3.10001
=> 000
mid3 -10001
=> 000
(mid3 -123)
=> 123
(mid3 -100)
=> 100
(mid3 100)
=> 100
(mid3 -12345)
=> 234

# Errors
mid3.1
=> nil
mid3.2
=> nil
mid3 -1
=> nil
mid3 -10
=> nil
mid3 2002
=> nil
mid3 -2002
=> nil
(mid3 0)
=> nil

[edit] 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);
];
]
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

[edit] zkl

fcn middle(ns){
ns.apply("toString").apply('-("-"))
.apply(fcn(n){nl:=n.len();
if(nl<3 or nl.isEven) return(False);
n[(nl-3)/2,3] : "%03d".fmt(_)
})
}
middle(T(123,12345,1234567,987654321,10001,-10001,-123,-100,100,-12345)).println()
middle(T(1, 2, -1, -10, 2002, -2002, 0)).println();
Output:
L("123","234","345","654","000","000","123","100","100","234")
L(False,False,False,False,False,False,False)

Algorithm is convert each number into a string, remove any "-", reject strings less then 3 characters or are even in length, return middle three characters of remainder.

Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox