11
\$\begingroup\$

This question already has an answer here:

Related

Explanation

Given a string such as DCBA, convert it to ASCII ordinals, such as 68 67 66 65. Then, take the differences between each value, eg 67 - 68 = -1, 66 - 67 = -1... giving -1 -1 -1 Now as long as there is more than 1 left over value, repeat getting the differences.

For a 3 letter string, your pathway should be similar to

A   F   G
65  70  71
-5  -1
-4

And for a 5 letter string...

B   A   C   E   D   F
66  65  67  69  68  70
1   -2  -2  1   -2
3   0   -3  3
3   3   -6
0   9
-9

The Challenge

Take a string input through any Standard IO Method, and output the value of the cumulative delta as described above.

Test Cases

input: cows
output: 8

input: helloworld
output: 905

input: aaaaaa
output: 0

input: abcdef
output: 0

input: ghfie
output: 20

input: CODEGOLF
output: 185

Rules

  • Standard Loopholes Apply
  • The input will only consist of ASCII letters that are either all uppercase or all lowercase
  • Your code MUST work for both lower and upper case.
  • The input will contain at least 2 characters.
  • The output may be positive or negative, as long as its absolute value matches the absolute value of the cumulative delta.
  • This is marked as , as such, shortest answer in bytes wins!
\$\endgroup\$

marked as duplicate by Martin Ender code-golf Oct 14 '16 at 7:49

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • \$\begingroup\$ What is the expected output for a single character input? Or is a single-character input even valid? \$\endgroup\$ – Suever Oct 14 '16 at 2:47
  • \$\begingroup\$ @Suever Presumably just the character's ordinal. \$\endgroup\$ – Mego Oct 14 '16 at 2:47
  • \$\begingroup\$ @Suever Behaviour undefined. I'll add a note under rules that a single character input will not be supplied. (Although the character's ordinal is what was outputted by my test code) \$\endgroup\$ – ATaco Oct 14 '16 at 2:48
  • 1
    \$\begingroup\$ Negatives would matter in all the intermediate steps, so I'm not sure why you'd want to ignore them in the final output. \$\endgroup\$ – Geobits Oct 14 '16 at 2:54
  • \$\begingroup\$ @Geobits If the string was taken in reverse, "FA" or "AF", the difference in the end cumulative delta is simply signage, "5" or "-5" respectively. The same applies for strings of any length. I've shown no biased for signage purely due to the fact that some languages consider deltas in different orders to others, to make the challenge slightly easier. \$\endgroup\$ – ATaco Oct 14 '16 at 2:57

12 Answers 12

6
\$\begingroup\$

Jelly, 6 4 bytes

-2 bytes thanks to @Dennis (implement a while loop)

OIṖ¿

TryItOnline
RunAllTestCases

How?

OIṖ¿ - Main link: s
O     - cast to ordinals
  Ṗ¿  - while, ¿, pop last value, Ṗ, evaluates to True:
 I    -     find increments between consecutive values
\$\endgroup\$
  • 1
    \$\begingroup\$ You can save two bytes with ¿ (while loop). \$\endgroup\$ – Dennis Oct 14 '16 at 2:59
  • \$\begingroup\$ @Dennis - I can never make while loops... \$\endgroup\$ – Jonathan Allan Oct 14 '16 at 3:01
  • \$\begingroup\$ OIṖ¿ does the job here. \$\endgroup\$ – Dennis Oct 14 '16 at 3:01
  • \$\begingroup\$ Huh the condition is pop? \$\endgroup\$ – Jonathan Allan Oct 14 '16 at 3:02
  • 1
    \$\begingroup\$ Yes. Once there's a single digit left, will return an empty array, breaking out of the loop. The condition doesn't affect the return value. \$\endgroup\$ – Dennis Oct 14 '16 at 3:03
9
\$\begingroup\$

Python 3, 71 bytes

s=input();k=r=0
for c in s:r=ord(c)-r*k/(len(s)-k);k+=1
print(round(r))

Test it on Ideone.

Alternate version, 58 bytes (inexact)

If an approximate result is enough – e.g., -904.9999999999993 ≈ -905 for input helloworld – then the following solution works as well.

f=lambda s,k=1:len(s)and-~-len(s)*f(s[1:],k+1)/k+ord(s[0])

Test it on Ideone.

Background

Proposition Let f be a variadic function that maps the code points s0, ⋯, sn to their cumulative delta with sign (-1)n, i.e.,

definition

Then

proposition

Proof The statement is clearly true when n = 0. Suppose that it holds for n - 1, where n > 0.

By the recursive definition of f and the hypothesis,

proof

By induction, the statement holds for all non-negative values of n.

How it works

Since

nCr

we can rewrite the proposition as follows.

formula

The iterative implementation does precisely this. Numerators are computed by incrementing k, denominators by subtracting k from the length of the input string s, i.e., n+1.

Unfortunately, not all fractions will evaluate to integers, so the result is computed using floating point arithmetic and finally rounded to the nearest integer.

The recursive implementation does roughly the same, but it keeps track of the denominator via the auxiliary variable k and computes the numerator by subtracting 1 from the length of the remaining string (~-len(s)).

\$\endgroup\$
  • \$\begingroup\$ The explanation currently has some bugs (mostly related to signs). I'll fix that asap. \$\endgroup\$ – Dennis Oct 14 '16 at 14:31
7
\$\begingroup\$

MATL, 5 bytes

`dtnq

Try it Online! or here is a slightly modified version for all test cases.

Explanation

        % Implicitly grab the input as a string
`       % Do....while loop
    d   % Compute the difference between all consecutive ASCII codes
    tnq % Determine the current length and subtract 1
        % Implicit end of do...while. Evaluate (and consume) stack element and break out
        % of loop if it's 0.
        % Implicit end of loop and display
\$\endgroup\$
  • \$\begingroup\$ Gosh Darn MATL. ...Have an explanation? \$\endgroup\$ – ATaco Oct 14 '16 at 2:44
  • \$\begingroup\$ @JonathanAllan As stated in the challenge, sign doesn't matter. \$\endgroup\$ – Suever Oct 14 '16 at 2:50
3
\$\begingroup\$

J, 15 bytes

<:@#2&(-/\)3&u:

Usage

   f =: <:@#2&(-/\)3&u:
   f 'cows'
8
   f 'helloworld'
_905
   f 'aaaaaa'
0
   f 'abcdef'
0
   f 'ghfie'
_20
   f 'CODEGOLF'
_185

Explanation

<:@#2&(-/\)3&u:  Input: string S
           3&u:  Ordinal of each char
   #             Get the length of S
<:@                Decrement it
    2&(   )      Repeat len(s)-1 times on x = ordinal(S)
    2    \         For each pair of values
       -/            Reduce using subtraction
                   Return that as the next value of x
                 Return the final x as the result
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 7 bytes

ÇDgG¥}`

Try it online!

Explanation

Ç        # convert to list of ascii codes
 DgG }   # length-1 times do:
    ¥    # take deltas
      `  # pop the single value left in the list and output
\$\endgroup\$
2
\$\begingroup\$

Python 2, 80 73 bytes

Saving 7 bytes thanks to Dennis.

L=map(ord,input())
while L[1:]:L=[x-y for x,y in zip(L,L[1:])]
print L[0]

Requires input to be given in quotes, e.g. "helloworld"

\$\endgroup\$
  • 2
    \$\begingroup\$ You can replace raw_input with input if you surround the string with quotes (allowed by default). Also, len(L)>1 can become L[1:]. \$\endgroup\$ – Dennis Oct 14 '16 at 5:55
1
\$\begingroup\$

RProgN, 17 Bytes

►Sb]L1-1\1:[d}P

Explination

►                   # Spaceless segment
 Sb                 # Convert the input to a stack, convert the stack of strings to a stack of ordinals.
   ]L               # Push a duplicate of that stack, pop it and push the length in its place
     1-             # Subtract 1 from the length.
       1\1          # Push a one, slide it under the top value, push another one, such that 1 LENGTH 1
          :  }      # For (i=1; i<=LENGTH; i+=1)
           [d       # Pop the iterator, pop the current stack, push the delta stack representing it.
              P     # Pop the top value of the stack, push it to the reg stack, and implicitly print.

I used (A version of) this script to test the question itself. I thought I might as well share it.

Try It Online!

\$\endgroup\$
1
\$\begingroup\$

Racket 147 bytes

(let p((l(map char->integer(string->list s))))(if(= 1(length l))(car l)(p
(for/list((i(range 1(length l))))(-(list-ref l(- i 1))(list-ref l i))))))

Ungolfed:

(define (f s)
  (let loop ((lst (map char->integer (string->list s))))
    (if (= 1 (length lst))
        (first lst)
        (loop (for/list ((i (range 1 (length lst))))
                (- (list-ref lst (sub1 i)) 
                   (list-ref lst i))
                )))))

Testing:

(f "AFG")
(f "BACEDF")
(f "cows")
(f "helloworld")
(f "abcdef")
(f "aaaaaa")
(f "ghfie")
(f "CODEGOLF")

Output:

-4
-9
8
-905
0
0
-20
-185
\$\endgroup\$
  • \$\begingroup\$ Signage doesn't matter for the answer. You can save those characters. \$\endgroup\$ – ATaco Oct 14 '16 at 4:11
  • \$\begingroup\$ Ok. Thanks. I will remove absolute function. \$\endgroup\$ – rnso Oct 14 '16 at 4:13
1
\$\begingroup\$

Haskell, 51 47 bytes

g[x]=x
g x=g$zipWith(-)=<<tail$x
g.map fromEnum

Usage example: g.map fromEnum $ "CODEGOLF"-> 185.

map fromEnum turns the string into a list of ascii values. If it has only a single element, return it, else build neighbor differences and check again.

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 116 bytes

Good that the input is more than 1 char so I can use s.length for both Arrays and Strings!

Snippet referenced from Neil's answer on another question :P

d=k=>/\d/.test(k)?k:k.charCodeAt(0);r=x=>(a=[...x],a.pop(),a.map((c,i)=>d(c)-d(x[i+1])));f=s=>s.length-1?f(r(s)):s[0]
<input oninput=o.textContent=this.value&&f(this.value)><pre id=o>

\$\endgroup\$
0
\$\begingroup\$

Brain-Flak, 97 bytes

([][()]<>){<>([][()]){({}[()]<({}[({})]<>)><>)}{}{}<>([]){({}[()]<({}<>)<>>)}{}<>({}<>[()])}<>

Try it online!

This is 97 bytes of code, plus 3 bytes for the -a flag, which enables ASCII input.

This would be a lot simpler if we didn't have to worry about the difference between characters sometimes being zero. Instead, we have to muck around with reversing the stack and pushing stack height several times.

Explanation:

Push the stack height onto the alternate stack
([][()]<>)

While this stack is non-empty:
{

    Move back
    <>

    Push the height of the stack minus one
    ([][()])

    While true
    {

        Decrement the stack height counter
        ({}[()]

        Move the difference over to the other stack
        <({}[({})]<>)><>)

    }

    Pop the last value and the left-over counter
    {}{}

    Move on to the other stack
    <>

    Move everything back
    ([]){({}[()]<({}<>)<>>)}

    Pop the counter
    {}<>

    Move the step number minus one back
    ({}<>[()])

End
}

Move back one last time
<>
\$\endgroup\$
0
\$\begingroup\$

R, 58 bytes

x=rev(utf8ToInt(readline()));while(length(x)>1)x=diff(x);x

diff() in R works differently than the difference defined in this challenge. Therfore we have reverse the vector (using rev) prior to taking the difference the first time.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.