Summing A String
June 19, 2020
We scan the string left to right, looking for digits and accumulating numbers where they appear. The first clause ends the iteration and reports the result, the second clause accumulates the current number, the third clause adds the previously-current number to the running sum, and the fourth clause skips non-digits:
(define (sum-string str)
(let loop ((cs (string->list str)) (curr 0) (sum 0))
(cond ((null? cs) (+ curr sum))
((char-numeric? (car cs))
(loop (cdr cs)
(+ (* curr 10)
(char->integer (car cs))
(- (char->integer #\0)))
sum))
((positive? curr)
(loop (cdr cs) 0 (+ curr sum)))
(else (loop (cdr cs) 0 sum)))))
Here are some examples:
> (sum-string "123abc45def") 168 > (sum-string "123abc45") 168 > (sum-string "abc123def45ghi") 168 > (sum-string "abcde") 0
You can run the program at https://ideone.com/PIo1fD.
In Python.
import re def sumstr(txt): return sum(int(n) for n in re.findall(r"(\d+)", txt)) txt = "77Pro123gra34mming Pra987xis is fun32" print(sumstr(txt)) # --> 1253Here are two solutions in standard Scheme (R7RS). The first is a “one
liner” that uses string-tokenize from SRFI 13. The second uses only
simple Scheme. It also reliably (based on my reading of R7RS) handles
numbers in character-sets other than ASCII. (See sample inputs.)
(import (scheme base) (scheme write) (scheme char) (only (srfi 14) char-set:digit) (only (srfi 13) string-tokenize string-fold)) (define samples ; ((input . output) ...) '(("123abc45def" . 168) ("" . 0) ("a-123bc45xyz" . 168) ("99bottles0corks" . 99) ("१२३कखग४५घङ" . 168) ("९९बाटल्या०बुच" . 99))) (define (string-numbers-sum str) (apply + (map string->number (string-tokenize str char-set:digit)))) (define (string-numbers-sum/v2 str) (let ((len (string-length str))) (let loop ((i 0) (pnum 0) (s 0)) (if (>= i len) s (let ((c (string-ref str i))) (if (char-numeric? c) (loop (+ i 1) (+ (* 10 pnum) (digit-value c)) s) (loop (+ i 1) 0 (+ s pnum)))))))) (define (demo f) (write (equal? (map cdr samples) (map f (map car samples)))) (newline)) (demo string-numbers-sum) (demo string-numbers-sum/v2)Output:
Here’s some Haskell. Scan the string accumulating digits, when a complete number is found, use base-10 arithmetic to add number into running total:
Here’s another Haskell version, using splitWhen from the “split” library.
Here’s a shell script solution.
sedis combined withtrto replace repeated non-digit characters with a+. This could alternatively be achieved by passingsed‘s flag for extended regex, and checking for one or more non-digit characters.Example:
Here’s a solution in C.
#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> // Overflow is not checked/handled. int main(int argc, char* argv[]) { assert(argc == 2); int sum = 0; int multiplier = 1; int n = strlen(argv[1]); for (int i = n - 1; i >= 0; --i) { char c = argv[1][i]; if (c < '0' || c > '9') { multiplier = 1; continue; } sum += multiplier * (int)(c - '0'); multiplier *= 10; } printf("%d\n", sum); return EXIT_SUCCESS; }Example:
@Daniel – nice solutions, scanning the string in reverse is a good idea, here’s a simplified version of my “elementary” Haskell solution:
I left an extra “0” in the test data there, so the result is actually “[5,7,3]”.
Here’s a simple solution: get a list of numbers in the string, then add them up. A Commonlisp implementation:
(defun split-string (str &key (pred #'(λ (c) (char= c #\space)))) "return a list of substrings of str delimited at positions where pred is T. The charcters at the point where pred is T are not included" (do ((i (1- (length str)) (1- i)) (current nil) (acc nil)) ((< i 0) (or (and (null current) acc) (cons (coerce current 'string) acc))) (let ((c (char str i))) (cond ((funcall pred c) (unless (null current) (push (coerce current 'string) acc)) (setf current nil)) (t (push c current)))))) (defun sum-numbers-in-string (str) "return the sum of the numbers in str where each number is contigous." (reduce #'(λ (a b) (+ a (parse-integer b))) (split-string str :pred #'alpha-char-p) :initial-value 0))A different approach in Python:
>>> f = lambda s: eval(re.sub("[^0-9]+","+",s).strip("+")) >>> f("123abc45def") 168Actually, that’s rather like Daniel’s shell solution.
Here is a different solution:
#123abc45def
st = input(“Enter string”)
sum_val = 0
msg = ”
for i in st:
if ord(i)>47 and ord(i)< 58:
msg+=i
else:
if msg!=”:
sum_val+=int(msg)
msg=”
else:
continue
print(sum_val)
public class Exercises_2 {
public static void main(String[] args) {
class Input{
public String inputString(){
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
public int string_in_int_out(String s){
int sum = 0;
char [] inputValue = s.toCharArray();
char [] numbers = new char [inputValue.length + 1];
for (int i = 0; i < inputValue.length; i++) {
if (Character.isDigit(inputValue[i])){
numbers[i] = inputValue[i];
}else {
continue;
}
}
String buffer = “”;
for (int i = 0; i < numbers.length; i++) {
if (!Character.isDigit(numbers[i])){
continue;
}else if(Character.isDigit(numbers[i])){
buffer += numbers[i];
if (!Character.isDigit(numbers[i + 1])){
sum += Integer.parseInt(buffer);
buffer = “”;
}
}
}
return sum;
}
}
Input input = new Input();
System.out.println(input.string_in_int_out(input.inputString()));
}
}
Hi guys how I can post my solutions like a code?
‘code’ blocks are best: https://wordpress.com/support/wordpress-editor/blocks/syntax-highlighter-code-block/2/
Here’s another solution in C.
#include <assert.h> #include <stdio.h> #include <stdlib.h> // Overflow is not checked/handled. int main(int argc, char* argv[]) { assert(argc == 2); long sum = 0; while (*argv[1]) { sum += strtol(argv[1], &argv[1], 10); if (*argv[1]) ++(argv[1]); } printf("%ld\n", sum); return EXIT_SUCCESS; }Example:
A bit late to the party…here is a one liner in Ruby:
Example:
solution in Clojure with transducer:
(ns stringsum.core (:require [clojure.string :as string] [clojure.edn :as edn]) (:gen-class)) (defn sum-numbers [str] (let [xf (comp (filter (complement string/blank?)) (map edn/read-string))] (transduce xf + 0 (string/split str #"[a-zA-Z]+"))))Although the regex should better be #”[^\d+]”
A naive Haskell solution
Here’s mine in Perl, using regexes
use strict; use warnings; use List::Util qw(reduce); my $str = "123abc45def"; print (reduce { $a + $b } ($str =~ /(\d+)/g));if (!empty($_POST['string'])) { $string = $_POST['string']; preg_match_all('/\d+/', $string, $matches); $total = 0; foreach ($matches as $match) { foreach ($match as $integer) { $total += $integer; } } echo "<pre>"; var_dump($matches); echo "The sum of all integers in the string that you have entered is: ".$total; } ?> <!DOCTYPE html> <html> <head> <title>Summing strings</title> </head> <body> <form action="SummingIntegersInString.php" method="POST"> <input name="string"> <button type="submit">Sum It!</button> </form> </body> </html>