26
\$\begingroup\$

(inspired by this post over on Puzzling. CAUTION: SPOILERS FOR THAT PUZZLE ARE BELOW.)

The standard telephone keypad correlates letters to numbers as follows:

1 ->
2 -> ABC
3 -> DEF
4 -> GHI
5 -> JKL
6 -> MNO
7 -> PQRS
8 -> TUV
9 -> WXYZ
0 ->

A given input word is defined to be an Ordered Word if, when translated to keypad presses using the above, the resulting number is either non-decreasing or non-increasing. In other words, the resultant number cannot both increase and decrease.

For example, the word CAT translates to 228, which is non-decreasing, and thus an Ordered Word. However, the word DOG is 364, which both increases and decreases, and thus is not an Ordered Word.

The challenge

Given a word, output whether or not it's Ordered.

Input

  • A word (not necessarily a dictionary word) consisting of ASCII alphabet ([A-Z] or [a-z]) letters only, in any suitable format.
  • Your choice if the input is all uppercase or all lowercase, but it must be consistent.
  • The word will be at least 3 characters in length.

Output

A consistent truthy/falsey value for whether the input word is Ordered (truthy) or not Ordered (falsey).

Rules

  • Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
  • If possible, please include a link to an online testing environment so other people can try out your code!
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.

Examples

Here are some Ordered Words (i.e., truthy), and there are more on the linked Puzzling puzzle.

CAT
TAC
AAA
DEMONS
SKID
LKJONMSRQP
ABCDEFGHIJKLMNOPQRSTUVWXYZ

Here are some non-Ordered Words (i.e., falsey)

DOG
GOD
ROSE
COFFEE
JKLMNOGHI
\$\endgroup\$
7
  • \$\begingroup\$ Related and Related I'm not sure this isn't a dupe, the only change between abc->t9 and this challenge is checking monotonicity? \$\endgroup\$
    – nmjcman101
    Jul 31, 2017 at 15:49
  • 1
    \$\begingroup\$ @nmjcman101 Yes, those are related, but there could be other (better?) ways than strictly abc->t9. \$\endgroup\$ Jul 31, 2017 at 15:57
  • \$\begingroup\$ That makes sense, I do hope to see something beat that method \$\endgroup\$
    – nmjcman101
    Jul 31, 2017 at 15:58
  • 1
    \$\begingroup\$ Also slightly related. \$\endgroup\$ Jul 31, 2017 at 16:08
  • \$\begingroup\$ Test case request: AAA \$\endgroup\$ Jul 31, 2017 at 16:12

24 Answers 24

14
\$\begingroup\$

Python 2, 164 148 132 77 bytes

-16 bytes thanks to Rod's suggestion elsewhere. A frickin' -55 bytes thanks to Arnold Palmer.

n=[min(int((ord(i)-58)/3.13),9)for i in input()]
print sorted(n)in[n,n[::-1]]

Try it online!

Input must be uppercase. Outputs True or False based on its orderedness.


Explanation

The first line maps each letter to a number.

                               for i in input()   # iterate over the input string
            ord(i)                                # take the ASCII ordinal
                  -58                             # subtract 58
           (         )/3.13                       # divide by 3.13
       int(                )                      # chop off the fractional part
   min(                     ,9)                   # choose the minimum between the number and 9
n=[                                            ]  # assign the resulting list to n

This works based on:

          | A   B   C  | D   E   F  | G   H   I  | J   K   L  | M   N   O  | P   Q   R   S  | T   U   V  | W   X   Y   Z
----------+------------+------------+------------+------------+------------+----------------+------------+-----------------
ord(x)    | 65  66  67 | 68  69  70 | 71  72  73 | 74  75  76 | 77  78  79 | 80  81  82  83 | 84  85  86 | 87  88  89  90
----------+------------+------------+------------+------------+------------+----------------+------------+-----------------
x - 58    | 7   8   9  | 10  11  12 | 13  14  15 | 16  17  18 | 19  20  21 | 22  23  24  25 | 26  27  28 | 29  30  31  32
----------+------------+------------+------------+------------+------------+----------------+------------+-----------------
x ÷ 3.13* | 2.2 2.6 2.9| 3.2 3.5 3.8| 4.2 4.5 4.8| 5.1 5.4 5.8| 6.1 6.4 6.7| 7.0 7.3 7.7 7.9| 8.3 8.6 8.9| 9.3 9.6 9.9 10.2
----------+------------+------------+------------+------------+------------+----------------+------------+-----------------
int(x)    | 2   2   2  | 3   3   3  | 4   4   4  | 5   5   5  | 6   6   6  | 7   7   7   7  | 8   8   8  | 9   9   9   10
----------+------------+------------+------------+------------+------------+----------------+------------+-----------------
min(x, 9) | 2   2   2  | 3   3   3  | 4   4   4  | 5   5   5  | 6   6   6  | 7   7   7   7  | 8   8   8  | 9   9   9   9

*Values are rounded. :P

The second line outputs if the list of numbers is in ascending or descending order.

print                                             # print whether...
      sorted(n)                                   # n sorted...
               in[n,n[::-1]]                      # is equivalent to n or n reversed
\$\endgroup\$
3
  • 4
    \$\begingroup\$ 84 bytes \$\endgroup\$ Jul 31, 2017 at 16:44
  • 1
    \$\begingroup\$ Holy cow, that's awesome. Thanks! \$\endgroup\$ Jul 31, 2017 at 16:45
  • \$\begingroup\$ I was going to post it as an answer cause I wrote it before everyone flooded in with answers, but you sniped me :) \$\endgroup\$ Jul 31, 2017 at 16:47
8
\$\begingroup\$

JavaScript (ES6),  83 ... 71  70 bytes

Returns a boolean.

x=>[...x].every(c=>v&=~(k=x,x=parseInt(c,35)*.32|0||10,x<k?2:x>k),v=3)

Test cases

let f =

x=>[...x].every(c=>v&=~(k=x,x=parseInt(c,35)*.32|0||10,x<k?2:x>k),v=3)

test = a => a.forEach(s => console.log(f(s) + " for '" + s + "'"))

console.log('[Truthy]')
test(["AAA", "CAT", "TAC", "DEMONS", "SKID", "LKJONMSRQP", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"])

console.log('[Falsy]')
test(["DOG", "GOD", "ROSE", "COFFEE", "JKLMNOGHI"])


How?

Letter conversion

We use parseInt(c, 35) to convert each letter of the input string to some number in [10 .. 34]. Because it's base-35, "Z" is converted to NaN instead.

The expression * .32 | 0 maps this number into the interval [3 .. 10], leading to 8 correct groups of letters for "A" to "Y". We need || 10 to get the correct value for "Z".

           | A  B  C| D  E  F| G  H  I| J  K  L| M  N  O| P  Q  R  S| T  U  V| W  X  Y   Z
-----------+--------+--------+--------+--------+--------+-----------+--------+------------
parseInt   |10 11 12|13 14 15|16 17 18|19 20 21|22 23 24|25 26 27 28|29 30 31|32 33 34 NaN
-----------+--------+--------+--------+--------+--------+-----------+--------+------------
*.32|0||10 | 3  3  3| 4  4  4| 5  5  5| 6  6  6| 7  7  7| 8  8  8  8| 9  9  9|10 10 10  10

Order test

We keep track of the signs of differences between consecutive numbers into the bitmask v, initially set to 3 (0b11):

  • bit #0: cleared when new_value > previous_value
  • bit #1: cleared when new_value < previous_value

The previous value is stored in the same variable x as the input. This ensures that the first iteration -- where no previous value actually exists -- will not clear any bit, because a string containing only letters is neither greater nor less than any number:

('CAT' > 5) === false
('CAT' < 5) === false

A word is ordered unless both signs are encountered, which leads to v = 0 and makes every() fail.

\$\endgroup\$
1
  • \$\begingroup\$ Oh, nice trick to get the number of each letter :) I'm torn as to whether I should borrow it or not, as it would mean I'd tie with you, which doesn't seem right. \$\endgroup\$
    – Shaggy
    Jul 31, 2017 at 16:44
6
\$\begingroup\$

Jelly, 28, 27, 25, 23, 22, 21, 19, 18 bytes

_>
O‘ç82ç88:3IṠḟ0E

Try it online!

This was a lot of fun to write!

Explanation:

                # Define a helper link, decrement a if a > b
_               # Subtract
 >              # Boolean greater than
                # Main link:
O               # The ordinals (ASCII points) of the input
 ‘              # Minus one
  ç82           # Decrement if greater than 82
     ç88        # Decrement if greater than 88
        :3      # Divide each number by 3
          I     # Consecutive differences
           Ṡ    # Sign (-1 if < 0, 0 if == 0, and 1 if > 0)
            ḟ0  # Remove all 0's
              E # All elements are equal?

Thanks to @ErikTheOutgolfer, @leakynun and @BusinessCat for all saving bytes. :)

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

05AB1E, 36 bytes

v.•1нJ©½è`ÇHø¹á₂N¸°…ÈáÀ•#Dʒyå}k}¥0‹Ë

Try it online!

\$\endgroup\$
6
  • 4
    \$\begingroup\$ You can replace .•1нJ©½è`ÇHø¹á₂N¸°…ÈáÀ•# by A•22ā₂•S£. \$\endgroup\$
    – Adnan
    Jul 31, 2017 at 19:22
  • 3
    \$\begingroup\$ @Adnan rip formatting \$\endgroup\$
    – Leaky Nun
    Jul 31, 2017 at 19:22
  • 3
    \$\begingroup\$ @LeakyNun <s>rip indeed</s> fixed \$\endgroup\$
    – Adnan
    Jul 31, 2017 at 19:22
  • 4
    \$\begingroup\$ @Adnan rip formatting \$\endgroup\$
    – Leaky Nun
    Jul 31, 2017 at 19:23
  • 4
    \$\begingroup\$ @LeakyNun rip indeed \$\endgroup\$
    – Adnan
    Jul 31, 2017 at 19:24
3
\$\begingroup\$

MATL, 26 25 bytes

1Y21K250B-Y{c&m8\dZSu|s2<

Input is in upper-case letters. Output is 1 or 0.

Try it online!

Explanation

1Y2      % Push 'ABC...XYZ'
1        % Push 1
K        % Push 4
250B     % Push 250 in binary, that is, [1 1 1 1 1 0 1 0]
-        % Subtract (from 4, element-wise): gives [3 3 3 3 3 4 1 4]
Y{       % Convert to cell array, splitting into chunks of those lengths
c        % Convert to char matrix. Gives a 4-column matrix. Chunks of length 3
         % are right-padded with a space
&m       % Implicit input. Push (linear) index of membership in char matrix
8\       % Modulo 8. Converts linear index into 0-based row index
d        % Consecutive differences
ZS       % Sign
u        % Unique
|        % Absolute value
s        % Sum
2<       % Less than 2? Implicit display
\$\endgroup\$
2
  • \$\begingroup\$ Appropriate score for an alphabetic challenge :P \$\endgroup\$
    – DJMcMayhem
    Jul 31, 2017 at 16:33
  • \$\begingroup\$ @DJMcMayhem Not anymore :-D \$\endgroup\$
    – Luis Mendo
    Jul 31, 2017 at 16:37
3
\$\begingroup\$

Husk, 22 21 19 18 bytes

±S€Ẋ▲`Ṫo±≤"DGJMPTW

Returns 1 for truthy inputs, 0 for falsy ones. Inputs must be in uppercase. Passes all test cases. Try it online!

Explanation

±S€Ẋ▲`Ṫo±≤"DGJMPTW  Implicit input x, e.g. "CAT"
     `Ṫo±≤"DGJMPTW  This part transforms x into a "canonical form" corresponding to the numpad digits
     `Ṫ             Table with flipped arguments
       o±≤          on sign of less-than-or-equal
                    (In Husk, ≤ returns extra information we don't want, so we take sign of the result to get 0 or 1.)
          "DGJMPTW  of this string and x.
                    This gives, for each char in x, a bit array of comparisons with the chars in the string:
                    y = [[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[1,1,1,1,1,1,0]]
   Ẋ▲               Maxima of adjacent pairs: [[0,0,0,0,0,0,0],[1,1,1,1,1,1,0]]
 S€                 1-based index in y as sublist: 2
±                   Sign: 1
\$\endgroup\$
3
\$\begingroup\$

Python 2, 60 bytes

a=[3681/ord(c)for c in input()]
print sorted(a)in[a,a[::-1]]

Try it online!

Accepts input in lowercase.

How it works

⌊3681/x⌋ decreases from

  • 38 to 37 at x ≈ 96.8684210526, before a;
  • 37 to 36 at x ≈ 99.4864864865, between c and d;
  • 36 to 35 at x ≈ 102.25, between f and g;
  • 35 to 34 at x ≈ 105.171428571, between i and j;
  • 34 to 33 at x ≈ 108.264705882, between l and m;
  • 33 to 32 at x ≈ 111.545454545, between o and p;
  • 32 to 31 at x ≈ 115.03125, between s and t;
  • 31 to 30 at x ≈ 118.741935484, between v and w;
  • 30 to 29 at x ≈ 122.7, after z.
\$\endgroup\$
2
\$\begingroup\$

C++, 375 199 195 194 bytes

Thanks to Shaggy's JavaScript answer :
-5 bytes thanks to Zacharý

#include<string>
int o(std::string a){std::string m="22233344455566677778889999";for(auto&b:a)b=m[b-65];int j=1,i=0,d=0;for(;j<a.size();++j){if(a[j]>a[j-1])++i;if(a[j]<a[j-1])++d;}return!(i*d);}
\$\endgroup\$
6
  • \$\begingroup\$ Can you move the int j=1,i=0,d=0 to the for loop? \$\endgroup\$
    – Adalynn
    Jul 31, 2017 at 22:57
  • \$\begingroup\$ @Zacharý Since i and d are used outside of the loop block, i can't \$\endgroup\$ Jul 31, 2017 at 23:17
  • \$\begingroup\$ i==0||d==0 ==> i*d==0. \$\endgroup\$
    – Adalynn
    Jul 31, 2017 at 23:20
  • \$\begingroup\$ Would !(i*d) work? (removing the space after return) \$\endgroup\$
    – Adalynn
    Jul 31, 2017 at 23:25
  • \$\begingroup\$ @Zacharý Yes, it works \$\endgroup\$ Jul 31, 2017 at 23:28
1
\$\begingroup\$

05AB1E, 30 bytes

A3 8×Ƶ0+S£¹δåā>‚øε`*}.«+¥0K0‹Ë

Try it online!

-1 thanks to Magic Octopus Urn.

\$\endgroup\$
4
  • \$\begingroup\$ Did you use ¥0K0.SË because ¥0‹Ë isn't correct? I can't tell if the 0.S is needed. \$\endgroup\$ Jul 31, 2017 at 15:52
  • \$\begingroup\$ @MagicOctopusUrn In fact ¥0K0‹Ë seems to work. \$\endgroup\$ Jul 31, 2017 at 15:54
  • \$\begingroup\$ Yeah, if you're removing the 0's it should; in my answer I'm not sure it works. \$\endgroup\$ Jul 31, 2017 at 15:55
  • \$\begingroup\$ @MagicOctopusUrn I'm removing the 0s since otherwise there will be false negatives. Your answer might behave differently though. \$\endgroup\$ Jul 31, 2017 at 15:55
1
\$\begingroup\$

Retina, 65 bytes

T`_ADGJMPTW`d
}T`L`_L
(.)\1*
$1$*1<
(1+)<(?!\1)
$1>
1

^(<*|>*)>$

Try it online! Link includes test cases. Explanation:

T`_ADGJMPTW`d

Change the first letter on each key to a digit. (This is off by 1 but that doesn't matter for an ascending/descending check. On the other hand, zeros would make my life more difficult, so I left one filler character in.)

}T`L`_L

Shuffle all the remaining letters up 1 and repeat until they've all been converted to digits.

(.)\1*
$1$*1<

Convert the digits into unary, but only once per run of identical digits. The unary values are seprated with a <...

(1+)<(?!\1)
$1>

... but if the LHS turns out to be greater than the RHS, correct the < to >.

1

Delete the 1s which are no longer necessary.

^(<*|>*)>$

Check that the word is ordered. (The trailing > comes from the last digit which always compares greater than the empty space following it.)

\$\endgroup\$
1
  • \$\begingroup\$ That's pretty cool. Thanks for the thorough explanation. \$\endgroup\$ Jul 31, 2017 at 20:06
1
\$\begingroup\$

Pyth, 23 bytes

One of my first non-trivial Pyth answer! Saved 6 bytes thanks to @LeakyNun. The initial solution is below.

/{_BKmhS,9/a58Cd3.13zSK

Test Suite.

Pyth, 29 bytes

KmhS+9]/-Cd58 3.13w|qKSKqK_SK

Test Suite.


Explanation

/{_BKmhS,9/a58Cd3.13zSKQ - The Q means evaluated input and is implicit at the end

 {                      - Deduplicate
  _                     - Reverse
   B                    - Bifurcate, Create a two-element list, [B, A(B)]
    K                   - Variable with auto-assignement to:
     m              z    - Map over the input:
      hS                  - Minimum (first element of sorted list)
        ,                 - Create a two-element list, [A, B] with these elements:
         9                  - The numeric literal 9
          /                 - The integer division of:
           a58Cd              - The absolute difference between 58 and ord(current_element)   
                3.13          - The numeric literal 3.13
                    SK   - K sorted
/                     Q  - Count the occurrences of the input in [K, K[::-1]]                
\$\endgroup\$
1
1
\$\begingroup\$

05AB1E, 21 17 bytes

Code

A•22ā₂•Sās×J‡Ô¥dË

Uses the 05AB1E encoding.

Try it online! or Verify all test cases!

Explanation

A                   # Push the lowercase alphabet
 •22ā₂•             # Push the number 33333434
       S            # Split into an array
        ā           # Get the range of indices [1 .. length]
         s×         # Swap and string multiply
           J        # Join that array
            ‡       # Transliterate

This now essentially maps the following letters to the following numbers:

abcdefghijklmnopqrstuvwxyz
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
11122233344455566667778888

             Ô      # Remove consecutive duplicates
              ¥     # Compute the delta's of the list
               d    # Check if the number is greater or equal to 0
                Ë   # Check if all elements are the same
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 107 97 95 92 88 85 bytes

Works with mixed-case strings. Returns 1 for truthy or 0 for falsey.

s=>(s=(a=[...s].map(c=>(parseInt(c,36)-3)/3.13%10|0||9))+"")==a.sort()|s==a.reverse()
  • 10 bytes saved thanks to Rod.

Try It

o.innerText=(f=
s=>(s=(a=[...s].map(c=>(parseInt(c,36)-3)/3.13%10|0||9))+"")==a.sort()|s==a.reverse()
)(i.value="Cat")
oninput=_=>o.innerText=f(i.value)
<input id=i><pre id=o>

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Math.min((parseInt(c,36)-3)/3.13|0,9) instead "2..9"[parseInt(c,36)-10] to save some bytes \$\endgroup\$
    – Rod
    Jul 31, 2017 at 16:26
  • \$\begingroup\$ Thanks, @Rod; very nice. I'll have to file that away for future use. \$\endgroup\$
    – Shaggy
    Jul 31, 2017 at 16:28
  • \$\begingroup\$ 86 bytes. \$\endgroup\$
    – user72349
    Jul 31, 2017 at 18:38
  • \$\begingroup\$ Thanks, @ThePirateBay, but,sadly, that fails for input AAA. \$\endgroup\$
    – Shaggy
    Aug 1, 2017 at 8:05
1
\$\begingroup\$

Gaia, 29 27 25 17 bytes

ċ⟨):“QX’>¦Σ⁻3/⟩¦o

Try it online!

Explanation

ċ                  Turn the input into a list of code points
 ⟨            ⟩¦   Map this block to each code point:
  )                 Increment it
   :                Copy it
    “QX’            Push [81 88]
        >¦          Check if the code point is greater than each of [81 88]
          Σ         Sum the results
           ⁻        Subtract from the code point
            3/      Integer divide the result by 3
                o  Check if the resulting list is in sorted order (increasing or decreasing)
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 13 bytes

ÇÍžq÷8
7:Ô¥dË

Whenever I see a numpad question, I have to make a pi-based answer.

Try it online or verify all test cases

Ç                    # ASCII code of each letter in the input
 Í                   # add 2
  žq÷                # divide by pi
     8 7:            # replace 8 with 7
         Ô           # remove duplicates
          ¥          # deltas
           d         # each >= 0 ?
            Ë        # are all elements equal?
\$\endgroup\$
0
\$\begingroup\$

Jelly, 32 bytes

“¢Ç⁺H’D0ẋj1œṗØA⁸=€×"€9Ḋ¤Fḟ0Iḟ0ṠE

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ RIP compression \$\endgroup\$
    – Leaky Nun
    Jul 31, 2017 at 19:22
  • \$\begingroup\$ @LeakyNun The compressed number is actually 32222323 so it saves just 2 bytes. \$\endgroup\$ Jul 31, 2017 at 19:26
0
\$\begingroup\$

C# (.NET Core), 133 bytes

using System.Linq;q=>{var u=q.Select(c=>(int)((c-58)/3.13));var z=u.Zip(u.Skip(1),(a,b)=>a-b);return!(z.Any(d=>d<0)&z.Any(d=>d>0));};

Try it online!

I feel like there's some room to save, but C# is not a concise language so maybe not. Ungolfed:

bool Ordered(string word){

    IEnumerable<int> keys = word.Select(character => (int)((character - 58)/3.13)); 
    // convert characters to keypad number

    IEnumerable<int> differences = keys.Zip(keys.Skip(1), (a, b)=> a-b); 
    // difference between consecutive elements

    return !(differences.Any(diff => diff<0) & differences.Any(diff => diff>0)); 
    // false if both positive and negative differences exist
}

In particular I think there's a shorter way to express the final check for validity, possibly a way to inline it with the Zip. Finding a way to express the Zip without needing temporary storage for the Skip would also save something, but I doubt there's something more concise for that.

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

Python 3, 143 147 148 149 130 bytes

def g(s,f=lambda c:min(int((ord(c)-58)/3.13),9)):x=[f(a)-f(b)for a,b in zip(s,s[1:])];return any(t<0for t in x)*any(t>0for t in x)

Best I can do for now. Crude function turns the letter into the number based off of ascii code. There are definitely some improvements to be made. 0 is truthy, 1 is falsey (sorry). Saved 10 bytes thanks to Rod, another 3 thanks to Mr. Xcoder.

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ you can use x=[f(a)-f(b)for a,b in zip(s,s[1:])] to save some bytes \$\endgroup\$
    – Rod
    Jul 31, 2017 at 16:33
  • \$\begingroup\$ also, min(int((ord(c)-58)/3.13),9) is a shorter way to convert the char \$\endgroup\$
    – Rod
    Jul 31, 2017 at 16:34
  • \$\begingroup\$ 140 bytes \$\endgroup\$
    – Mr. Xcoder
    Jul 31, 2017 at 16:38
  • \$\begingroup\$ @Rod Thanks! Very helpful. \$\endgroup\$
    – C McAvoy
    Jul 31, 2017 at 16:38
  • \$\begingroup\$ You'll need to swap your outputs around in order for this to be valid. \$\endgroup\$
    – Shaggy
    Jul 31, 2017 at 22:24
0
\$\begingroup\$

Python 2, 111 103 bytes

-8 bytes thanks to @Arnold Palmer:no lower() needed

  • Takes uppercase letters as input.
lambda x:sorted(f(x))in[f(x),f(x)[::-1]]
f=lambda x:['22233344455566677778889999'[ord(i)-65]for i in x]

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can remove the .lower() since the input can be in whatever case you specify. \$\endgroup\$ Jul 31, 2017 at 19:28
0
\$\begingroup\$

PHP 7, 98+1 95+1 84+1 bytes

a golfed port of Arnauld´s answer.

for(;$c=ord($argn[$i]);$v|=$i++?$p>$k?2:$p<$k:0,$p=$k)$k=($c-58)*.32%10?:9;echo$v<3;

accepts uppercase; empty output for falsy, 1 for truthy.

Run as pipe with -nR or try it online.

original post:

for(;$c=$argn[$i++];$p?$a[]=$p<=>$k:0,$p=$k)$k=(ord($c)-58)/3.13-($c>Y)|0;echo min($a)*max($a)>=0;
\$\endgroup\$
0
\$\begingroup\$

CJam, 37 31 30 27 bytes

q{_"SVZY"#g-i3/}%_$_W%](e=g

Try it Online

Of course the ugly version ends up being shorter...

q{        e# For each character in string...
_"SVZY"#g e# Get index of that character in "SVZY". Signum that. (returns 1 or 0 if inside string, -1 if not.)
-i3/      e# Subtract value from character (i.e 'Z' becomes 'Y', 'F' becomes 'G'). Convert to int. Integer divide by 3. (this is just how the math works out for proper mapping of characters to phone digits.)
}%
_$_W%]    e# Put mapped string, sorted version, and reverse sorted version in array.
(         e# Pop mapped string from array onto stack.
e=        e# Count occurences of mapped string in array.
g         e# Signum.
\$\endgroup\$
0
\$\begingroup\$

C (gcc), 183 169 153 117 bytes

#define a(b)(int)fmin(*(b c)/3.2,27)
d(char*c){int r=1,p=1;for(;1<strlen(c);)r&=a()<=a(1+),p&=a()>=a(++);return r|p;}

Try it online!

Old solution:

#define a(b)(int)((int)(b*.32-17.6)*.9)
d(char*c){int l=~-strlen(c),i=0,r=1,p=1;for(;i<l;++i)r&=a(c[i])<=a(c[i+1]),p&=a(c[l-i])<=a(c[l-i-1]);return r+p;}

Saved 8 bytes thanks to ThePirateBay.

Old old solution:

d(char*c){char*a="22233344455566677778889999";int l=strlen(c)-1,i=0,r=1,p=1;for(;i<l;++i){if(a[c[i]-65]>a[c[i+1]-65])r=0;if(a[c[l-i]-65]>a[c[l-i-1]-65])p=0;}return r+p;}

Old old old solution:

d(char*c){char*a="22233344455566677778889999";int l=strlen(c);int i,r=1,p=1;for(;i<l-1;++i)if(a[c[i]-65]>a[c[i+1]-65])r=0;for(i=l-1;i>0;--i)if(a[c[i]-65]>a[c[i-1]-65])p=0;return r+p;}
\$\endgroup\$
0
0
\$\begingroup\$

TI-Basic, 92 66 bytes

ΔList(int(seq(inString("BC DEF GHI JKL MNO PQRSTUV WXYZ",sub(Ans,I,1))/4,I,1,length(Ans
0≤min(Ansmax(Ans

Converts each character in the string to an integer from 0 to 7, and takes the difference between each consecutive element; then checks whether the minimum and maximum differences have the same sign (or either is 0).

\$\endgroup\$
1
  • \$\begingroup\$ I think ΔList(int(4^-1seq(inString("DEF GHI JKL MNO PQRSTUV WXYZ",sub(Ans,I,1))+3,I,1,length(Ans saves one byte. \$\endgroup\$
    – lirtosiast
    Aug 25, 2017 at 0:17
0
\$\begingroup\$

Zsh, 73 69 57 bytes

-12 bytes by using @anders-kaseorg's 3681/code conversion.

for c (${(s::)1})((y=3681/#c,A|=y<p,D|=p&&p<y,p=y,!D|!A))

Try it online! Try it online! Try it online!

A few things we abuse:

  • ((statement,statement,...)) is a sequence of arithmetic expressions which returns truthy if the last statement is non-zero.
  • The return value of a loop is the return value of the last statement in a loop.
  • Arithmetic operator precedences were pretty nice to us, as only one pair of no parentheses were used. One byte could be saved if ! bound less tightly than &.
  • Unset parameters expand to 0 in arithmetic expansions.
  • The function we use to map to the keypad number is CODE / 3.2 - 18 (with a special case for Z), but since we only need the change between codes, we don't do the linear adjustment.
for c (${(s::)1})           # split into characters
    (( y = #c-90 ? 0^(#c/3.2) : 27,   # this sets y to the keypad number + 18
       A |= y < p,          # set the A flag if we detect it is not ascending
       D |= p && p < y,     # ditto descending, don't compare on first iteration
       p = y,               # save the current character
       !D | !A              # return false if D and A are both set
    ))

2 bytes can be saved if the truthy/falsey values can be swapped.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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