Middle three digits: Difference between revisions
(→{{header|Ruby}}: Move output into pre element..) |
(→{{header|Ruby}}: Improve output formatting.) |
||
Line 563:
end
samples = [
]
width = samples.map { |n| n.to_s.length }.max
samples.each do |n|
print "#{n}: "
begin
Line 573 ⟶ 580:
end</lang>
Output:
<pre> 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
</pre>
=={{header|Rust}}==
<lang rust>fn middle_three_digits(x: int) -> Result<~str, ~str> {
|
Revision as of 04:16, 5 February 2013
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.”
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.
C++
<lang 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;
} </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 d>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
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 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>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 "Number must have at least three digits" if l < 3 raise "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 "#{n}: " begin puts "%03d" % middle_three_digits(n) rescue RuntimeError => 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
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
- 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