22
\$\begingroup\$

Write a program that accepts a single lowercase word as input and outputs the number of pairs of letters that have the same number of letters between them in the word as in the alphabet.

For example, in the word 'nature', we have 4 pairs:

  • nr: since there are three letters between them inside the word (a, t, u) and three letters between them in the alphabet (o, p, q)
  • ae: since there are three letters between them inside the word (t, u, r) and three letters between them in the alphabet (b, c, d)
  • tu: since there are no letters between them inside the word and no letters between them in the alphabet
  • tr: since there is one letter between them inside the word (u) and one letter between them in the alphabet (s)

Since there are four pairs, the output in this case should be 4.

\$\endgroup\$
  • 10
    \$\begingroup\$ The wording can be clarified a bit more. \$\endgroup\$ – Optimizer Nov 8 '15 at 12:15
  • \$\begingroup\$ I don't get the question. How are the letters a,t,u going to be inside nr? And all the following examples... (cc @flodel) \$\endgroup\$ – nicael Nov 8 '15 at 15:25
  • \$\begingroup\$ If you spell out n.a.t.u.r.e, the n and r are at the 1st and 5th position. So there are three letters between them. They are a, t, and u, at the 2nd, 3rd and 4th position. That's what the text means by there are three letters between n and r inside the word. \$\endgroup\$ – flodel Nov 8 '15 at 16:36
  • \$\begingroup\$ @flodel You're right in the edit; I missed the 4th pair. \$\endgroup\$ – ghosts_in_the_code Nov 10 '15 at 8:42
  • \$\begingroup\$ What if the word were rjjjnfffr? Would that be one pair (nr) or two pairs (nr and rn)? And what about abzab? Is that two pairs of ab or one? \$\endgroup\$ – Not that Charles Nov 17 '15 at 19:22

13 Answers 13

5
\$\begingroup\$

Pyth, 19 bytes

lfqF-MSMCT.cCUBCMz2

Try it online: Demonstration

Explanation:

lfqF-MSMCT.cCUBCMz2
                 z   read a string from input
               CM    convert into list of ascii-values
            CUB      create a list of pairs (ascii-value, index in string)
          .c      2  all combinations of length 2
 f                   filter for combinations T, which satisfy:
        CT              transpose T ((ascii1, ascii2), (index1, index2)
      SM                sort each list
    -M                  create the the difference for each
  qF                    check if they are equal
l                    print the number of remaining combinations
\$\endgroup\$
4
\$\begingroup\$

R, 110 bytes

function(s){w=strsplit(s,"")[[1]]
O=outer
n=nchar(s)
sum(abs(O(r<-match(w,letters),r,"-"))==O(1:n,1:n,"-"))-n}

Degolfed:

F = function(s){
   chars = strsplit(s,"")[[1]]
   num_chars = nchar(s)
   letter_rank = match(chars, letters)
   rank_dist = abs(outer(letter_rank, letter_rank, "-"))
   position_dist = outer(1:num_chars, 1:num_chars, "-")
   return(sum(rank_dist == position_dist) - num_chars)
}

F("nature")
# [1] 4
F("supercalifragilisticexpialidocious")
# [1] 25
\$\endgroup\$
3
\$\begingroup\$

Octave, 41 bytes

@(s)nnz(abs(s-s')==(t=1:(u=nnz(s)))-t')-u
\$\endgroup\$
3
\$\begingroup\$

CJam, 36 bytes

r:A,{)Aew}%1>{{:B,B0=BW=-z)=}%}%e_:+

Try it Online.

\$\endgroup\$
2
\$\begingroup\$

J, 27 bytes

#-:@-~#\+/@,@:=&(|@-/~)3&u:

Usage:

   (#-:@-~#\+/@,@:=&(|@-/~)3&u:) 'nature'
4

Explanation:

#-:@-~#\+/@,@:=&(|@-/~)3&u:
      #\                    lengths of input prefixes (1,2,...,length)
                       3&u: codepoints of input
               &(     )     with the last two do parallel:
                 |@-/~      create difference table with itself and take absolute values
              =             compare the elements of the two difference tables
        +/@,@:              sum the table              
#   -~                      subtract the length of the input (self-similar letters)
 -:@                        half the result (each pair was accounted twice)

Try it online here.

\$\endgroup\$
2
\$\begingroup\$

CJam, 25 bytes

l:T,_2m*{_:-\Tf=:-z=},,\-

Try it online

Explanation:

l     Get input.
:T    Store in variable T for later use.
,     Calculate length.
_     Copy for use at the very end.
2m*   Use Cartesian power to calculate all possible position pairs.
{     Start filter.
  _     Create copy of index pair.
  :-    Calculate difference between indices.
  \     Swap copy of index pair to top.
  T     Get input string stored in variable T.
  f=    Extract the letters for the index pair.
  :-    Calculate difference of the two letters.
  z     Take the absolute value.
  =     Compare index difference and letter difference.
},    End filter.
,\
-     Pairs of identical indices passed the filter. Eliminate them from the
      count by subtracting the length of the input.
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 98 bytes

f=w=>(p=0,q="charCodeAt",[...w].map((c,a)=>{for(b=a;w[++b];)p+=Math.abs(w[q](a)-w[q](b))==b-a}),p)

Usage

f("nature")
=> 4

Explanation

f=w=>(
  p=0,                                 // p = number of pairs
  q="charCodeAt",
  [...w].map((c,a)=>{                  // iterate through each character of input
                                       // a = character A index
    for(b=a;w[++b];)                   // iterate through the remaining input characters
                                       // b = character B index
      p+=                              // add 1 to p if true or 0 if false
        Math.abs(w[q](a)-w[q](b))==b-a // compare absolute difference of character codes
                                       //     to difference of indices
  }),
  p                                    // return p
)
\$\endgroup\$
1
\$\begingroup\$

Python 2, 91 chars

lambda i:sum(y-x==abs(ord(i[y])-ord(i[x]))for x in range(len(i))for y in range(x+1,len(i)))
\$\endgroup\$
1
\$\begingroup\$

MATLAB, 84 bytes

s=input('');disp(sum(diff(nchoosek(find(s),2),[],2)==abs(diff(nchoosek(s,2),[],2))))

This line asks for a string as input. It then creates all possible pairs of letters and does the same for their corresponding indices. Then we determine whether the (absolute) difference of the values matches to finally sum all cases where it does. The result is displayed in the command window.

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

JavaScript ES7, 93

Using array comprehension. ES6 with .map.map.map is 2 bytes longer.

Test running the snippet below with Firefox

f=s=>[for(x of s)x.charCodeAt()].map((a,i,s)=>s.map((b,j)=>t+=j>i&(b>a?b-a:a-b)==j-i),t=0)&&t

document.write('nature'+'\n'+f('nature'))

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

PowerShell, 114 100 Bytes

param($a)$b=$a.length;0..($b-1)|%{$i=$_;($_+1)..$b|%{$o+=[math]::Abs(+$a[$_]-$a[$i])-eq($_-$i)}};+$o

Pretty straight-forward, but uses a couple tricks.

  • param(..) takes our input, saves it to $a.
  • We set a temp variable $b to be the .length of our input. This saves a byte later.
  • 0..($b-1)|%{..} is the equivalent of a for($i=0;$i-le($b-1);$i++){..} loop, but quite a lot shorter.
  • However, we need to set variable $i in order to keep that going into ...
  • ($_+1)..$b|%{..} the next for loop, since $_ is only positional to the inner loop.
  • We then use a lengthy .NET call to check if the absolute value between our two characters (here we use implicit casting with prepending + to save a bunch of bytes) is -equal to the positional difference in the array. Since we're explicitly given lowercase input, we don't need to do case conversion. This statement will return either True or False.
  • We blatantly abuse implicit casting again to accumulate that result into $o, so True will add 1, while False will add 0.
  • Once the loops are finished, we output $o. Note we need to do the same tricksy-cast-to-int with + to avoid printing False if there were no matches.
\$\endgroup\$
0
\$\begingroup\$

Ruby, 74

 ->s{[*0...s.size].permutation(2).count{|i,j|(s[i].ord-s[j].ord).abs==j-i}}

Nothing super interesting here. I would have loved to use eval("s[i].#{["succ"]*(j-i)*?.}") but... seemed too long.

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

Matlab(94)(80)

Edit: I didnt take in case inversed alphabetic order,as (t,r) in 'nature', so more bytes to upweight :(

@(a)sum(arrayfun(@(x)sum(1:nnz(find(a==fix(x/2)+(-1)^x*(1:1:nnz(a))))-1),2:244))

  • binomial function throws a stupid exception when k is bigger than n and I cant catch exceptions inside arraycell function, otherwise I could golf it more. Who needs a built in function ??

    Now I could just do it by hand, simplifying binomial(n,2)=n/(2(n-2)!)=n(n-1)/2. remark that this last value reprensents sum of integers from 1 to n-1, this doesnt throw any exception in matlab, God bless maths.

  • Ps: this method is diferent than slvrbld's

Execution

  >> ans('abef')

  ans =

       2

  >> ans('abcd')

  ans =

       6

  >> ans('nature')

  ans =

       4
\$\endgroup\$
  • \$\begingroup\$ I think it's safe to remove ,'s' from input()'s arguments. Saves you 4 bytes. Furthermore, it seems to fail on longer strings (e.g. 'supercalifragilisticexpialidocious' that flodel used as test case) due to the hardcoded for-loop range... you may want to fix that. \$\endgroup\$ – slvrbld Nov 12 '15 at 8:14
  • \$\begingroup\$ @slvrbld i doont think i need that,see the newest edit \$\endgroup\$ – Abr001am Nov 17 '15 at 22:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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