I've been trying to think of ways to do it, I can't just convert the string to an int. It's too long to be an int, that's the reason I need to do this. I can do it for single digits, but as soon as I want to add say 10 or 20 I'm not sure how to change my code to allow that. If I increase the loop it will increase the length of the string and that wouldn't be treating it as an actual number. The reason I include two languages is because I will accept C# or F# code in an answer.
open System
type String with
member this.Last() =
this.[this.Length - 1]
let mutable s = "1234567890" // the numbers I will use are a lot bigger than this.
for i in 0 .. 9 do // 9 is max before it increases the length of the string.
printfn "%s" s
let last = (s.Last().ToString() |> int) + 1
s <- s.[0 .. s.Length - 2] + last.ToString()
Console.Read() |> ignore
I doubt there is any situation where using strings to represent numbers would be a good idea - you can use BigInteger
to represent and work with large numbers and it supports all numerical operations, not just incrementing by one.
However, it is a fun problem, so here is one possible F# solution:
let incString (s:string) =
let rec loop acc carry i (s:string) =
match i, carry with
| -1, true -> System.String(Array.ofList ('1'::acc))
| -1, false -> System.String(Array.ofList acc)
| _ ->
match s.[i], carry with
| '9', true -> loop ('0'::acc) true (i-1) s
| c, false -> loop (c::acc) false (i-1) s
| c, true -> loop (char ((int c) + 1)::acc) false (i-1) s
loop [] true (s.Length-1) s
incString "9899"
The inner loop
function takes the following parameters:
acc
is an accumulator, used to collect digits of the new number (starting from the end) carry
is a boolean flag that is true
if we want to add 1
to the next number (this is initially true
and then it is also true
as long as the digits are 9
- because 9
will become 0
and we then need to add to the next digit in the string).
i
is the current index, starting from the last one
s
is the input string representing the original number.
you reverse it into a list of chars the try to increment the lowest digit, if that doesnt work (its a 9), you set the lowest digit to '0' and recurse the tail
let inc: string -> string =
let rec incRev: List<char> -> List<char> =
function
| [] -> [ '1' ]
| '9' :: cs -> '0' :: incRev cs
| c :: cs -> char (int c + 1) :: cs
fun s ->
s.ToCharArray()
|> Array.toList
|> List.rev
|> incRev
|> List.rev
|> Array.ofList
|> System.String
another probably slightly more efficient answer (I prefer the previous one), but doesnt have all the reversing going on. you fold from the back of the list of chars assembling an answer and passing the carry digit up to the end.
let inc2: string -> string =
let incDigit : (char * (List<char> * char)) -> (List<char> * char) =
function
| (c,(a,'0')) -> (c :: a,'0')
| ('9',(a,'1')) -> ('0' :: a,'1')
| (c,(a,'1')) -> ((char (int c + 1)) :: a,'0')
fun s ->
let result =
(s.ToCharArray()
|> Array.toList
|> List.foldBack (fun c state -> incDigit (c,state))) ([],'1')
result
|> fst
|> if (snd result = '1') then (fun cs -> '1' :: cs) else id
|> Array.ofList
|> System.String
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.