Decode the Dreaded Alphabet Cypher™️

33

5

This challenge is inspired by one of my other challenges: Pointlessly make your way down the alphabet

That challenge asked you to take a string of text, and for each letter produce a sequence of letters moving down the alphabet to 'a'.

For this challenge I'd like to decode the output of that challenge (minus the line breaks), to find a human-readable string from a much longer human readable string.


Here is some text which has been encoded using the Dreaded Alphabet Cypher™️

hgfedcbaedcbalkjihgfedcbalkjihgfedcbaonmlkjihgfedcba wvutsrqponmlkjihgfedcbaonmlkjihgfedcbarqponmlkjihgfedcbalkjihgfedcbadcba

It consists of descending alphabetical sequences, ending in an 'a'. The first character in each of these sequences is a letter in the decoded text. (A space is still a space).

The challenge

  • Write code to convert a Dreaded Alphabet Cypher™️ encoded string into a decoded, human-readable string.
  • No need to validate if it is a Dreaded Alphabet Cypher™️ string, I'm not interested in how it handles invalid input.
  • Use any language you please.
  • Please include a link to an online iterpreter.
  • The input will only consist of lower-case letters and spaces. No upper cases, punctuation etc.
  • Code golf, try to write short code, standard loopholes etc.

Test Cases

Input:

hgfedcbaedcbalkjihgfedcbalkjihgfedcbaonmlkjihgfedcba wvutsrqponmlkjihgfedcbaonmlkjihgfedcbarqponmlkjihgfedcbalkjihgfedcbadcba

Output:

hello world

Input:

abacbadcbaedcbafedcbagfedcbahgfedcbaihgfedcbajihgfedcbakjihgfedcbalkjihgfedcbamlkjihgfedcbanmlkjihgfedcbaonmlkjihgfedcbaponmlkjihgfedcbaqponmlkjihgfedcbarqponmlkjihgfedcbasrqponmlkjihgfedcbatsrqponmlkjihgfedcbautsrqponmlkjihgfedcbavutsrqponmlkjihgfedcbawvutsrqponmlkjihgfedcbaxwvutsrqponmlkjihgfedcbayxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba

Output:

abcdefghijklmnopqrstuvwxyz

(beware the multiple a's)

Input:

aarqponmlkjihgfedcbaonmlkjihgfedcbanmlkjihgfedcba a aarqponmlkjihgfedcbaonmlkjihgfedcbanmlkjihgfedcbasrqponmlkjihgfedcbaonmlkjihgfedcbanmlkjihgfedcba hgfedcbaasrqponmlkjihgfedcba anmlkjihgfedcba aarqponmlkjihgfedcbadcbavutsrqponmlkjihgfedcbaarqponmlkjihgfedcbakjihgfedcba

Output:

aaron a aaronson has an aardvark

Input:

hgfedcbaaponmlkjihgfedcbaponmlkjihgfedcbayxwvutsrqponmlkjihgfedcba gfedcbaonmlkjihgfedcbalkjihgfedcbafedcbaihgfedcbanmlkjihgfedcbagfedcba

Output (is a secret, shh)

AJFaraday

Posted 2019-11-29T12:47:38.897

Reputation: 10 466

May the input contain leading or trailing spaces, or several spaces in a row? – Arnauld – 2019-11-29T14:17:51.857

@Arnauld I'm happy with trailing and leading spaces, but not within the result itself. – AJFaraday – 2019-11-29T14:19:05.550

Sorry, I meant the input, not the output. (I've edited my previous comment.) – Arnauld – 2019-11-29T14:20:08.197

@Arnauld The input could have trailing and leading spaces. – AJFaraday – 2019-11-29T16:43:07.867

May our input & output types differ (e.g. string in, list of characters out?) - maybe we have a meta consensus...? – Jonathan Allan – 2019-11-29T18:38:48.403

1@JonathanAllan sounds fine to me – AJFaraday – 2019-11-29T19:12:57.207

Alexa, announce "hgfedcbaedcbalkjihgfedcbalkjihgfedcbaonmlkjihgfedcba wvutsrqponmlkjihgfedcbaonmlkjihgfedcbarqponmlkjihgfedcbalkjihgfedcbadcba" – MooseBoys – 2019-12-02T10:31:36.297

Answers

16

JavaScript (ES9),  37 33  26 bytes

Returns an array of characters.

Either a negative look-behind:

s=>s.match(/(?<![b-z])./g)

Try it online!

Or a positive look-behind:

s=>s.match(/(?<=a| |^)./g)

Try it online!


25 bytes

If the input is guaranteed not to contain leading or double spaces (or we're allowed to remove and collapse them respectively), the positive look-behind can be made 1 byte shorter:

s=>s.match(/(?<=a|\b)./g)

Try it online!

Arnauld

Posted 2019-11-29T12:47:38.897

Reputation: 111 334

13

Haskell, 32 bytes

f s=[y|(x,y)<-zip('a':s)s,x<'b']

Try it online!

For each pair of consecutive characters, if the first one is 'a' or ' ', output the second one. Prepends an 'a' to the string so that the first character is always output.

Doorknob

Posted 2019-11-29T12:47:38.897

Reputation: 68 138

11

Jelly, 6 bytes

OŻI‘Tị

A monadic Link accepting a list of characters which yields a list of characters.

Try it online!

How?

OŻI‘Tị - Link: list of characters, S   e.g. "  baadcba  acbaedcba  "
                                       i.e. [' ',' ','b','a','a','d','c','b','a',' ',' ','a','c','b','a','e','d','c','b','a',' ',' ']
O      - to ordinal (vectorises across S)   [ 32, 32, 98, 97, 97,100, 99, 98, 97, 32, 32, 97, 99, 98, 97,101,100, 99, 98, 97, 32, 32]
 Ż     - prepend a zero                 [  0, 32, 32, 98, 97, 97,100, 99, 98, 97, 32, 32, 97, 99, 98, 97,101,100, 99, 98, 97, 32, 32]
  I    - incremental differences            [ 32,  0, 66, -1,  0,  3, -1, -1, -1,-65,  0, 65,  2, -1, -1,  4, -1, -1, -1, -1,-65,  0]
   ‘   - increment (vectorises)             [ 33,  1, 67,  0,  1,  4,  0,  0,  0,-64,  1, 66,  3,  0,  0,  5,  0,  0,  0,  0,-64,  1]
    T  - truthy indices                     [  1,  2,  3,      5,  6,             10, 11, 12, 13,         16,                 21, 22]
     ị - index into (S)                     [' ',' ','b',    'a','d',             ' ',' ','a','c',       'e',                ' ',' ']
                                       i.e. "  bad  ace  "

Jonathan Allan

Posted 2019-11-29T12:47:38.897

Reputation: 67 804

8

Perl 5 (-p), 15, 16 bytes

s/[b-z]\K.*?a//g

Try it online!

or using options trick

Perl 5 (-nF/(?<![\x20a])(?!^)[b-z]*a/), 7 bytes

print@F

Try it online!

Nahuel Fouilleul

Posted 2019-11-29T12:47:38.897

Reputation: 5 582

8

J, 22 13 12 bytes

–9 bytes, thanks @Jonah!

#~1,1-{:I.}:

Try it online!

FrownyFrog

Posted 2019-11-29T12:47:38.897

Reputation: 3 112

2

13 bytes: #~1,98>3 u:}: (Try it online!)

– Jonah – 2019-12-01T13:15:09.923

8

Python 3, 43 bytes

lambda s:[r for l,r in zip(' '+s,s)if'b'>l]

An unnamed function accepting a string which returns a list of characters.

Try it online!


To accept & return lists use ...zip([' ']+s... instead (45)

To accept & return strings use lambda s:''.join(r for l,r in zip(' '+s,s)if'b'>l) (50)

Jonathan Allan

Posted 2019-11-29T12:47:38.897

Reputation: 67 804

7

05AB1E, 9 8 bytes

-1 byte thanks to Kevin Cruijssen

AηíR¬S.:

Try it online!

Grimmy

Posted 2019-11-29T12:47:38.897

Reputation: 12 521

18 bytes by replacing ASR with ¬S. – Kevin Cruijssen – 2019-11-29T14:47:26.683

@KevinCruijssen Nice catch, thanks! – Grimmy – 2019-11-29T14:54:30.730

7

Japt -g, 10 9 8 bytes

óÈ¥YcÄÃy

Try it

ó           split between those characters that return true when passed through...
 È    Ã     function :
  ¥         x equal to..
   YcÄ      character next to y
       y   transpose

Flag -g used to get 1st element 

Saved 1 thanks to @Shaggy

AZTECCO

Posted 2019-11-29T12:47:38.897

Reputation: 2 441

11dYc can be YcÄ – Shaggy – 2019-11-29T16:47:52.670

I don't know why ó> or ò< won't work here; was trying them earlier. – Shaggy – 2019-11-29T16:49:06.767

I was trying something similar too but nothing worked – AZTECCO – 2019-11-29T17:30:11.603

And yet ... https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=UzwnYQ

– Shaggy – 2019-11-29T18:35:39.810

@Shaggy i moved to japt chat – AZTECCO – 2019-11-29T19:32:20.933

7

C (clang), 100 98 96 95 94 92 90 88 64 46 bytes

Saved 24 bytes thanks to @Neil!!!
Saved 18 bytes thanks to @dingledooper (removed #include<stdio.h>)

f(char*c){while(*c)for(putchar(*c);*c++>97;);}

Try it online!

Noodle9

Posted 2019-11-29T12:47:38.897

Reputation: 2 776

Why not just while(*n>97)? – Neil – 2019-11-30T20:41:55.417

Also, by putting putchar(*c); before the while loop, I was able to replace all uses of n with c. – Neil – 2019-11-30T20:46:14.857

In fact, by changing the while loop into a for loop you can move the putchar(*c) into the initialiser, saving you a pair of {}s. – Neil – 2019-11-30T20:47:23.503

@Neil Thanks so much, that's amazing! And now I can finally have a post-increment as part of the condition expression. :-) – Noodle9 – 2019-11-30T22:26:16.067

Thanks for posting this; the loop structure was useful for an x86 machine code implementation

– Peter Cordes – 2019-12-02T06:48:43.070

6

R, 57 56 bytes

-1 byte thanks to Giuseppe.

function(s)intToUtf8(c(v<-utf8ToInt(s),0)[c(0,v)%%32<2])

Try it online!

Could probably be made shorter with a regex, but this is more R-like. Converts to integers (vector v), then keeps only the first character and the characters which follow a space or an a. Since the corresponding codepoints are 32 and 97, we can check whether \$v_i\mod 32 <2\$ to get the relevant entries.

Robin Ryder

Posted 2019-11-29T12:47:38.897

Reputation: 6 625

156 bytes using in-line assignment instead of a function argument – Giuseppe – 2019-12-02T20:57:23.583

@Giuseppe Thanks! – Robin Ryder – 2019-12-02T21:09:20.837

5

JavaScript, 35 32 31 bytes

s=>s.replace(/ |.*?a/g,x=>x[0])

Try it online!

Shaggy

Posted 2019-11-29T12:47:38.897

Reputation: 24 623

5

Haskell, 59 bytes

f""=""
f(x:s)|x<'b'=x:(f s)|1>0=x:(f$tail$dropWhile(>'a')s)

Try it online!

No match for regex solutions, but I figured I'd try a recursive solution.

79037662

Posted 2019-11-29T12:47:38.897

Reputation: 1 739

57 bytes – Jo King – 2019-11-30T01:13:42.927

5

Japt, 9 bytes

Outputs an array of characters.

óÈkSiaîÎ

Try it

óÈkSiaîΠ    :Implicit input of string
ó             :Partition after characters that return falsey (empty string)
 È            :When passed through the following function
  k           :  Remove all characters in
   S          :    Space
    ia        :    Prepended with "a"
      Ã       :End function
       ®      :Map
        Î     :  First character

Shaggy

Posted 2019-11-29T12:47:38.897

Reputation: 24 623

5

Ruby, 28 bytes

->s{s.scan(/(?<=a|\b)./)*""}

Try it online!

This is a port of Arnauld's Javascript answer to Ruby.

game0ver

Posted 2019-11-29T12:47:38.897

Reputation: 621

5

K (oK), 14 bytes

{x@&1,98>-1_x}

Try it online!

Inspired by FrownyFrog's/Jonah's J solution

Galen Ivanov

Posted 2019-11-29T12:47:38.897

Reputation: 13 815

4

SNOBOL4 (CSNOBOL4), 106 bytes

	I =INPUT
S	I LEN(1) . X	:F(O)
	O =O X
	R =
	REVERSE(&LCASE) X REM . R
	I X R REM . I	:(S)
O	OUTPUT =O
END

Try it online!

	I =INPUT			;* Read input
S	I LEN(1) . X	:F(O)		;* extract the first letter or goto O if none exist
	O =O X				;* append that letter to the output
	R =				;* set R to the empty string
	REVERSE(&LCASE) X REM . R	;* Set R to the letters up to 'a', starting at X.
					;* R is empty string if X is space or 'a'
	I X R REM . I	:(S)		;* Set the REMainder of I after (X + R) to I; goto S
O	OUTPUT =O			;* output the string
END

Giuseppe

Posted 2019-11-29T12:47:38.897

Reputation: 21 077

4

Jelly, 10 bytes

Ḳµ=Ṃk⁸ZḢ)K

Try it online!

A monadic link taking a Jelly string and returning a Jelly string. When run as a full program takes a string as its argument and implicitly prints the output string.

Nick Kennedy

Posted 2019-11-29T12:47:38.897

Reputation: 11 829

4

C# (Visual C# Interactive Compiler), 33 bytes

x=>x.Where((_,l)=>l<1||x[l-1]<98)

Try it online!

Embodiment of Ignorance

Posted 2019-11-29T12:47:38.897

Reputation: 7 014

4

Red, 74 bytes

func[s][parse s[any[copy t thru"a"(prin#"`"+ length? t)opt[sp(prin sp)]]]]

Try it online!

Galen Ivanov

Posted 2019-11-29T12:47:38.897

Reputation: 13 815

4

braingasm, 20 18 bytes

,[.32-n[65-$[,]],]

It's been a while since I worked on braingasm. There seems to be a compare function, but I guess I didn't come around to implement a way to use the result. Well, this works:

,                    #  Read a byte from input
 [               ]   #  While the current byte is not zero
  .                  #    Print it
   32-               #    Decrease by 32
      n[       ]     #    If the result is non-zero (meaning it wasn't a space):
        65-          #      Subtract 65, leaving 'a' => 0, 'b' => 1, 'c' => 3, etc
           $[,]      #      That many times, read a byte from input
                ,    #    Read another byte

Doesn't handle newlines or anything other than lowercase letters and spaces in the input.

daniero

Posted 2019-11-29T12:47:38.897

Reputation: 17 193

4

Pip, 12 bytes

aR`\w*?a`_@0

Try it online!

Explanation

a             The input, as a command-line argument
 R            Do a regex replacement:
  `\w*?a`      Match a non-greedy series of letters ending in a
         _@0   Replace with the first character of the match

DLosc

Posted 2019-11-29T12:47:38.897

Reputation: 21 213

4

C (clang), 66 48 bytes

edit: -18 bytes thanks to @dingledooper (removed #include)

P;D(char*T){*T?P>97||putchar(*T),P=*T++,D(T):0;}

Try it online!

int P;          // previous character
D(char*T)
{
    if (*T)     // check for end of string
    {
        if (!(P > 'a'))     // output current if previous was 'a' or ' '
            putchar(*T);
        P = *T;             // update previous
        D(T + 1);           // find next
    }
}

xibu

Posted 2019-11-29T12:47:38.897

Reputation: 361

1You can remove the #include <stdio.h>, by the way – dingledooper – 2019-11-30T18:45:31.143

@dingledooper that's interesting, I didn't know that C allows calling standard functions without including the appropriate header. – xibu – 2019-11-30T19:11:33.653

@xibu: It's not recommended, but yes C89 has default-promotion rules for what happens when calling a function for which no prototype exists. If the actual definition of the function is compatible with the args you passed it, it works. If not, UB with no detection at compile time of the mismatch. – Peter Cordes – 2019-12-02T02:51:00.760

4

x86 machine code, 12 bytes

(Runs in any mode, 16-bit, 32-bit, or 64-bit.)

This is based on @Noodle9's C algorithm, but with rearrangement into do{}while asm loop structure.

NASM listing: address, machine code (hex dump of the actual answer), source

 1                             decda:  ; (char *dst=RDI, const char *src=RSI)
 2 00000000 AC                     lodsb             ; AL = *src++
 3                             .loop:                ; do{
 4 00000001 AA                     stosb                 ; *dst++ = AL
 5                                .skip_until_a:         ; do{
 6 00000002 3C61                    cmp  al, 'a'
 7 00000004 AC                      lodsb
 8 00000005 77FB                    ja  .skip_until_a    ; }while((AL=*p++) > 'a')
 9 00000007 84C0                   test al,al
10 00000009 75F6                   jnz .loop         ; } while(AL != terminator)
11                             ;    stosb             ; append a terminating 0
12 0000000B C3                     ret
                       ; output end pointer returned in RDI

Try it online!

The input is an implicit-length (0-terminated) C string. The output is an explicit-length buffer. This function returns (in RDI) a pointer to one-past-the-end.

(The caller already knows where the output buf starts, so it has C++-like .begin and .end iterators). Making this function append a terminating 0 would cost 1 extra byte for another stosb after the loop, unless there's a way to rearrange things that I'm not seeing.


A sample caller that passes the output of decda(argv[1]) to a write system call is included in the TIO link. You can inc edx in that caller to prove that the output didn't over-write beyond where it's supposed to.

I had been thinking of using loop .loop instead of test al,al/jnz but then the inner loop would need a dec ecx or something. (Without that, it loops until writing RCX output bytes, which only works if the caller knows the decrypted length, not the source length.) Worth considering for a 32-bit-only version that can use 1-byte dec ecx, unless that could reach loop or loopne with ECX<=0 for valid inputs.

Peter Cordes

Posted 2019-11-29T12:47:38.897

Reputation: 2 810

Very nice! I assembled and tested this on 16-bit MASM 1.1 and passes all tests perfectly. :) – 640KB – 2019-12-05T18:36:32.603

1@640KB: cool, I only tested it on x86-64 Linux. Well-golfed machine code is often independent of mode thanks to using implicit increments and sizes so I was pretty sure about my claim of working in any mode, but nice to have it tested :) – Peter Cordes – 2019-12-05T18:39:29.250

3

C# (Visual C# Interactive Compiler), 69 bytes

Hard to beat Regex on this one

s=>System.Text.RegularExpressions.Regex.Replace(s,"([b-z]).*?a","$1")

Try it online!

Returns an array of Matches (characters), 64 bytes

s=>System.Text.RegularExpressions.Regex.Matches(s,"(?<![b-z]).")

Try it online!

Innat3

Posted 2019-11-29T12:47:38.897

Reputation: 791

3

Keg, -ir, -lp, 9 7 bytes

(⑩(a-|_

Try it online!

2 bytes saved thanks to @A̲̲ suggesting to use a for loop over a while loop

Answer History

{!|⑩(a-|_

Try it online!

{!|⑩(a-|_
{!|             #While there are still items on the stack:
   ⑩            #Print t.o.s without popping
    (a-|            #Subtract the code point of a from tos and repeat that many times:
        _           #Pop items off the stack

Lyxal

Posted 2019-11-29T12:47:38.897

Reputation: 5 253

7 bytes. A simple optimization from while to for. (Your current program also generates an error in the end, so..) – None – 2019-11-30T12:34:07.760

@A No, not at all. I... I wouldn't have thought of using a for loop... I was going to add a 'loop while there are still items on the stack' command to get this down to 6 bytes. – Lyxal – 2019-11-30T21:28:40.903

3

Perl, 20 bytes

s:[^a]*a(.):a$_\1:g;

is almost there. Unfortunately, it will lose the first letter, and I don’t know how to get around that.

WGroleau

Posted 2019-11-29T12:47:38.897

Reputation: 131

Just add an a on the beginning! "a$_" =~ .... – Will Crawford – 2019-11-30T13:08:50.673

Doesn’t $ match the end of the string? And the underscore? – WGroleau – 2019-11-30T17:19:38.960

$_ is the string! "a$" is equivalent to concatenating "a" and $ ... – Will Crawford – 2019-11-30T17:49:45.553

I edited according to how I interpret your comment, but either it's wrong or I misunderstood. What I put in would make every output start with 'a'. Can you edit it so that it is correct? (Not that it competes with the length of a few others.) – WGroleau – 2019-11-30T19:07:45.597

Oh, no, I meant, apply the regex to "a$" (I'm assuming you use "perl -ne" or "perl -pe", so each line will be available as $). – Will Crawford – 2019-11-30T22:35:36.437

OK, that adds seven more bytes if I stick to ASCII. – WGroleau – 2019-12-01T08:04:30.087

3

Gema, 41 characters

\A\P?=?
 \P?=$0
?\P?=@cmps{?;?;$2;$2;}
?=

Unfortunately recognizers can not be combined. ☹

Sample run:

bash-5.0$ gema '\A\P?=$0; \P?=$0;?\P?=@cmps{$1;$2;$2;$2;};?=' <<< 'cbagfedcba cbacba'
cg cc

Try it online!

manatwork

Posted 2019-11-29T12:47:38.897

Reputation: 17 865

3

C++, 464 bytes

I'm still a beginner so will be grateful for any advice.

#include <iostream>
#include <string>
using namespace std;

int main() {
  string input , output;
  getline(cin,input);
  output = input[0];

  for (int i = 0 ; i<input.size() ; i++) {
      if (input[i] == 'a')  {
          output += input[i+1];
      }  else if (input[i] == ' ') {
          output += input[i+1];
      }  else {
          continue;
      }

  }
  cout << output;
}

Try it online!

Dorrineeee

Posted 2019-11-29T12:47:38.897

Reputation: 39

1

I don't know much about C++, but 212 bytes

– Lyxal – 2019-12-01T05:37:03.730

Also, welcome to CGCC! I hope you enjoy golfing answers to challenges while you're here! – Lyxal – 2019-12-01T05:38:10.450

Get a warning for 159 bytes

– None – 2019-12-01T07:44:03.487

As a first step, definitely remove all whitespace (including newline) and unneeded {}. And always use single-letter variable names. You can include an "ungolfed" version of your code in your answer (with newlines and comments) so people can read it. See also Tips for golfing in C++

– Peter Cordes – 2019-12-02T02:55:20.450

2

The <string> header is already included in <iostream>, the number of times you need std:: is way less bytes than using namespace std;, std::string::operator[](size_t pos) will return '\0' for pos == size(). and your if statement can be collapsed to checking if the current character is less than 98('b'). 122 bytes. :-)

– Noodle9 – 2019-12-02T14:27:51.583

And just found out about #import to save another byte 121 bytes.

– Noodle9 – 2019-12-02T17:31:16.150

Building on @Noodle9 120 bytes

– ceilingcat – 2019-12-14T00:27:39.587

2

Python 3.8 (pre-release), 50 bytes

import re
f=lambda s:re.sub('([b-z]).*?a',r'\1',s)

Regex stolen from Arnauld's JavaScript answer.

Try it online!

L. F.

Posted 2019-11-29T12:47:38.897

Reputation: 147

1

You can save 2 more bytes easily...

– game0ver – 2019-11-29T13:29:59.173

@game0ver I'm not familiar with the rules of the site, but does that count as a function? – L. F. – 2019-11-29T13:34:01.460

1Yes lambda is autonomous except for e.g. a recursive function where you need to refer to f... – game0ver – 2019-11-29T13:35:56.100

@game0ver But you can't just do something like print((lambda s:... import re)(input())) right? – L. F. – 2019-11-29T13:37:01.187

If you mean to place that all in the Footer then no. Your code must be an autonomous complete function/program. A lambda can be used standalone in a e.g. map etc... – game0ver – 2019-11-29T13:39:44.757

works fine in earlier versions of python3 and even in python 2.7. – Skyler – 2019-12-02T20:44:14.027

2

Python 2, 87 86 84 bytes

lambda i:"".join(x[:2]if'a'>x else x[0]for x in i.replace('a','a#').split('#')[:-1])

Try it online!

Non-regex effort. Replaces a with a plus a disposable character then splits on the disposable character and outputs either the first or first two letters of each list element depending on whether the first is a space or not.

ElPedro

Posted 2019-11-29T12:47:38.897

Reputation: 5 301

2

Jelly, 20 bytes

O0;ṡ2_/>0ƊÐḟṪ€Ọ
ḲÇ€K

Try it online!

probably too long lol

Explanation

O0;ṡ2_/>0ƊÐḟṪ€Ọ  This challenge, for one word
O                turn all the chars to their ASCII forms
 0;              prepend 0
   ṡ2            split into (overlapping) slices of length 2 (pairs)
          Ðḟ     filter: remove elements where
     _/          reducing over subtraction (which is equivalent to the first minus the second, in each pair)
       >0        is greater than 0 (if it's strictly descending)
            Ṫ€   take the second element of each pair
              Ọ  convert back to chars
ḲÇ€K             Compiled Program
Ḳ                split on spaces
 ǀ              apply the helper to each word
   K             join on spaces

HyperNeutrino

Posted 2019-11-29T12:47:38.897

Reputation: 26 575

2

Ruby, 20 + 1 bytes

gsub /(?<!a|\b)./,''

1 extra byte for the p command line option:

$ ruby -p alphabet_cypher.rb <<< "hgfedcbaedcbalkjihgfedcbalkjihgfedcbaonmlkjihgfedcba wvutsrqponmlkjihgfedgfedcbarqponmlkjihgfedcbalkjihgfedcbadcba"
hello world

Try it online!

daniero

Posted 2019-11-29T12:47:38.897

Reputation: 17 193

2

Charcoal, 8 bytes

Φ苧θ⊖κb

Try it online! Link is to verbose version of code. Explanation:

 θ          Input string
Φ           Filtered where
    θ       Input string
   §        Cyclically indexed by
      κ     Current index
     ⊖      Decremented
  ‹         Is less than
       b    Literal string `b`
            Implicitly print

Neil

Posted 2019-11-29T12:47:38.897

Reputation: 95 035

2

Wren, 67 bytes

Non-regex effort. I can't use regex because Wren doesn't support it..

Fn.new{|x|x.replace(" "," a").split("a")[0..-2].map{|i|(i+"a")[0]}}

Explanation

Fn.new{|x|                                                        } // New anonymous function with parameter x.
          x.replace(" "," a")                                       // Append spaces with the a character in order to make them individual.
                             .split("a")                            // Split into a list with the character a.
                                        [0..-2]                     // We have a trailing unused a, so we need to remove it.
                                               .map{|i|          }  // Foreach this list:
                                                       (i+"a")      // Append this item with an a character(since we have used it for the splitting function)
                                                              [0]   // Return the first item in this list

Try it online!

user85052

Posted 2019-11-29T12:47:38.897

Reputation:

2

Java (JDK), 35 bytes

s->s.replaceAll("([b-z]).*?a","$1")

Try it online!

Olivier Grégoire

Posted 2019-11-29T12:47:38.897

Reputation: 10 647

2

J, 18 bytes

({.;.2~'a'=])&>@;:

Try it online!

hoosierEE

Posted 2019-11-29T12:47:38.897

Reputation: 760

1You don't need the outer parenthesis. – Adám – 2019-12-03T21:01:09.467

2

Burlesque, 21 19 bytes

{'`+]2CO:so)[-}ww\[

Try it online!

Non-regex solution, can save 2 bytes if permitted to return list of chars

{
 `'+] # Prefix each word with a backtick
 2CO  # Create n-grams of length 2 (abc => {ab bc})
 :so  # Filter for those which are in alphabetical order
 )[-  # Take the last letter of each n-gram
}ww   # For each word
\[    # Concatenate to string

DeathIncarnate

Posted 2019-11-29T12:47:38.897

Reputation: 916

1

PHP, 67 bytes

According to the definition, we don't have to worry about invalid input. So I'm not actually checking if all the letters between the intended letter and "a" are properly following the reverse alphabet order, or even if there's the right number of letters. Feels a bit dirty, but it works for all valid input :)

for($x=0;$c=$argn[$x++];){$l=$l?$l:$c;if(ord($c)<98){echo$l;$l=0;}}

Try it online!

XMark

Posted 2019-11-29T12:47:38.897

Reputation: 141