From b883d90c632d7c6fb585ee23327705e308d65594 Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Mon, 2 Jan 2023 19:24:28 +0200 Subject: Use ranges like in Rust --- mendeleev.c | 21 +++++++++------------ mendeleev.cpp | 19 +++++++++---------- mendeleev.f90 | 25 ++++++++++++------------- mendeleev.lisp | 21 +++++++-------------- mendeleev.py | 36 +++++++++++++++--------------------- 5 files changed, 52 insertions(+), 70 deletions(-) diff --git a/mendeleev.c b/mendeleev.c index cad0308..5739cde 100644 --- a/mendeleev.c +++ b/mendeleev.c @@ -15,8 +15,6 @@ static const char *const ELEMENTS[] = { "?", "Tm", "Ts", "U", "V", "W", "Xe", "Y", "Yb", "Zn", "Zr" }; -static const size_t NELEMENTS = sizeof (ELEMENTS) / sizeof (const char *) - 1; - typedef struct element { size_t n; @@ -26,12 +24,12 @@ typedef struct element } element_t; static void -search (size_t *start, size_t *len, size_t shift, char c) +search (size_t *start, size_t *end, size_t shift, char c) { size_t l, m, u; c |= ' '; - u = *start + *len; + u = *end; l = *start; while (l < u) { @@ -42,13 +40,13 @@ search (size_t *start, size_t *len, size_t shift, char c) u = m; } - if ((l == *start + *len) || ((ELEMENTS[l][shift] | ' ') != c)) + if ((l == *end) || ((ELEMENTS[l][shift] | ' ') != c)) { - *len = 0; + *end = 0; return; } - u = *start + *len; + u = *end; *start = l; while (l < u) { @@ -59,7 +57,7 @@ search (size_t *start, size_t *len, size_t shift, char c) l = m + 1; } - *len = u - *start; + *end = u; } static element_t * @@ -69,13 +67,13 @@ split (const char *tail) element_t *last = NULL; size_t start = 1; - size_t len = NELEMENTS; + size_t end = sizeof (ELEMENTS) / sizeof (ELEMENTS[0]); size_t shift = 0; while (tail[shift]) { - search (&start, &len, shift, tail[shift]); - if (!len) + search (&start, &end, shift, tail[shift]); + if (start >= end) break; shift++; @@ -94,7 +92,6 @@ split (const char *tail) last->n = start; last->tail = &tail[shift]; start++; - len--; } } diff --git a/mendeleev.cpp b/mendeleev.cpp index cd2a8d3..7a52e48 100644 --- a/mendeleev.cpp +++ b/mendeleev.cpp @@ -34,11 +34,11 @@ struct Element { : eid(eid_), next(next_) {} }; -static void search(size_t &start, size_t &len, size_t shift, char c) { +static void search(size_t &start, size_t &end, size_t shift, char c) { size_t l, m, u; c |= ' '; - u = start + len; + u = end; l = start; while (l < u) { m = (l + u) / 2; @@ -48,12 +48,12 @@ static void search(size_t &start, size_t &len, size_t shift, char c) { u = m; } - if ((l == start + len) || ((ELEMENTS[l][shift] | ' ') != c)) { - len = 0; + if ((l == end) || ((ELEMENTS[l][shift] | ' ') != c)) { + end = 0; return; } - u = start + len; + u = end; start = l; while (l < u) { m = (l + u) / 2; @@ -63,26 +63,25 @@ static void search(size_t &start, size_t &len, size_t shift, char c) { l = m + 1; } - len = u - start; + end = u; } static list split(string_view tail) { auto x = list(); size_t start = 1; - size_t len = ELEMENTS.size() - 1; + size_t end = ELEMENTS.size(); size_t shift = 0; while (shift < tail.length()) { - search(start, len, shift, tail[shift]); - if (!len) + search(start, end, shift, tail[shift]); + if (start >= end) break; shift++; if (shift == ELEMENTS[start].length()) { x.emplace_back(start, tail.substr(shift)); start++; - len--; } } diff --git a/mendeleev.f90 b/mendeleev.f90 index 95640d0..e36bef7 100644 --- a/mendeleev.f90 +++ b/mendeleev.f90 @@ -67,15 +67,15 @@ contains end function tolower - pure subroutine search(start, length, sh, c) - integer, intent(in out) :: start, length + pure subroutine search(start, end, sh, c) + integer, intent(in out) :: start, end integer, intent(in) :: sh character(len=1), intent(in) :: c integer :: l, m, u, c_ c_ = tolower(c) - u = start + length + u = end l = start do while (l < u) m = (u + l) / 2 @@ -86,17 +86,17 @@ contains endif end do - if (l == start + length) then - length = 0 + if (l == end) then + end = 0 return end if if (tolower(ELEMENTS(l)(sh:sh)) /= c_) then - length = 0 + end = 0 return end if - u = start + length + u = end start = l do while (l < u) m = (u + l) / 2 @@ -107,23 +107,23 @@ contains endif end do - length = u - start + end = u end subroutine search function split(tail) result(head) character(len=:), pointer, intent(in) :: tail type(element_t), pointer :: head, last, el - integer :: start, length, sh + integer :: start, end, sh head => null() last => null() start = 1 - length = ubound(ELEMENTS, 1) + end = ubound(ELEMENTS, 1) + 1 do sh = 1, len(tail) - call search(start, length, sh, tail(sh:sh)) - if (length == 0) exit + call search(start, end, sh, tail(sh:sh)) + if (start >= end) exit if (sh == len_trim(ELEMENTS(start))) then allocate(el) @@ -138,7 +138,6 @@ contains last%tail => tail(sh+1:) start = start + 1 - length = length - 1 end if end do diff --git a/mendeleev.lisp b/mendeleev.lisp index a7e7945..611fd57 100644 --- a/mendeleev.lisp +++ b/mendeleev.lisp @@ -11,9 +11,6 @@ "Sg" "Si" "Sm" "Sn" "Sr" "Ta" "Tb" "Tc" "Te" "Th" "Ti" "Tl" "Tm" "Ts" "U" "V" "W" "Xe" "Y" "Yb" "Zn" "Zr")) -(defconstant +nelems+ - (1- (length +elements+))) - (defconstant +elems+ (map 'vector #'string-downcase +elements+)) @@ -21,37 +18,33 @@ (schar (elt +elems+ el) sh)) (defun search-el (range sh ch) - (prog* ((top (+ (car range) (cdr range))) - (u top) - (l (car range)) - m) + (prog ((l (car range)) (u (cdr range)) m) (loop while (< l u) do (setf m (truncate (+ l u) 2)) (if (char< (get-part m sh) ch) (setf l (1+ m)) (setf u m))) - (when (or (= l top) (char/= ch (get-part l sh))) + (when (or (= l (cdr range)) (char/= ch (get-part l sh))) (setf (cdr range) 0) (return)) - (setf u top - (car range) l) + (setf (car range) l u (cdr range)) (loop while (< l u) do (setf m (truncate (+ l u) 2)) (if (char< ch (get-part m sh)) (setf u m) (setf l (1+ m)))) - (setf (cdr range) (- u (car range))) (return))) + (setf (cdr range) u) (return))) (defun split (tail) - (prog ((range (cons 1 +nelems+)) + (prog ((range (cons 1 (length +elements+))) (sh 0) (r ())) (loop (search-el range sh (schar tail sh)) - (when (= 0 (cdr range)) (return)) + (when (>= (car range) (cdr range)) (return)) (incf sh) (when (= sh (length (elt +elems+ (car range)))) (push (cons (car range) (subseq tail sh)) r) - (incf (car range)) (decf (cdr range))) + (incf (car range))) (when (= sh (length tail)) (return))) (when (null r) (push (cons 0 (subseq tail 1)) r)) (return (reverse r)))) diff --git a/mendeleev.py b/mendeleev.py index f5ab020..6c01e0d 100644 --- a/mendeleev.py +++ b/mendeleev.py @@ -19,9 +19,9 @@ ELEMENTS = [ elements = [el.lower().encode() for el in ELEMENTS] -def search(start, length, shift, char): - upper = start + length - lower = start +def search(rng, shift, char): + upper = rng[1] + lower = rng[0] while lower < upper: mid = int((lower + upper) / 2) if elements[mid][shift] < char: @@ -29,14 +29,12 @@ def search(start, length, shift, char): else: upper = mid - if lower == start + length: - return (0, 0) + if lower == rng[1] or elements[lower][shift] != char: + rng[1] = 0 + return - if elements[lower][shift] != char: - return (0, 0) - - upper = start + length - start = lower + upper = rng[1] + rng[0] = lower while lower < upper: mid = int((lower + upper) / 2) if char < elements[mid][shift]: @@ -44,28 +42,24 @@ def search(start, length, shift, char): else: lower = mid + 1 - length = upper - start - - return (start, length) + rng[1] = upper def split(tail): result = [] - start = 0 - length = len(ELEMENTS) + rng = [0, len(ELEMENTS)] shift = 0 while shift < len(tail): - start, length = search(start, length, shift, tail[shift]) - if length == 0: + search(rng, shift, tail[shift]) + if rng[0] >= rng[1]: break shift += 1 - if len(elements[start]) == shift: - result.append((ELEMENTS[start], tail[shift:])) - start += 1 - length -= 1 + if len(elements[rng[0]]) == shift: + result.append((ELEMENTS[rng[0]], tail[shift:])) + rng[0] += 1 return result or [("?", tail[1:])] -- cgit v1.2.3