25
\$\begingroup\$

Rearrange a given list such that all the odd numbers appear before all the even numbers. Besides for this requirement, the output list may be in any order.

The input will only contain integers, but they may be negative and there may be duplicates, and they may appear in any order.

Shortest solution wins.

Test cases

[1,2][1,2]

[2,1][1,2]

[1,0,0][1,0,0]

[0,0,-1][-1,0,0]

[3,4,3][3,3,4]

[-4,3,3][3,3,-4]

[2,2,2,3][3,2,2,2]

[3,2,2,2,1,2][1,3,2,2,2,2] or [3,1,2,2,2,2]

[-2,-2,-2,-1,-2,-3][-1,-3,-2,-2,-2,-2,] or [-3,-1,-2,-2,-2,-2,]

[][]

\$\endgroup\$
16
  • \$\begingroup\$ Ty. Good question. Answer: odd numbers can come in any order. :) \$\endgroup\$ Commented Jul 18, 2018 at 5:37
  • 11
    \$\begingroup\$ Even though the challenge is quite simple, adding some test cases would be nice. E.g. at first glance I thought the block of odd and even numbers also needs to be sorted. \$\endgroup\$
    – Laikoni
    Commented Jul 18, 2018 at 7:17
  • 1
    \$\begingroup\$ @AsoneTuhid Yes:), numbers can repeat. \$\endgroup\$ Commented Jul 18, 2018 at 9:47
  • 11
    \$\begingroup\$ @Willmore You never know with code golf, rules are important. Please use the Sandbox next time to clarify your question before you post it. \$\endgroup\$ Commented Jul 18, 2018 at 10:09
  • 13
    \$\begingroup\$ Please edit your question to include the clarifications you gave in the comments. \$\endgroup\$
    – Laikoni
    Commented Jul 18, 2018 at 11:18

65 Answers 65

12
\$\begingroup\$

05AB1E, 2 bytes

ΣÉ

Try it online!

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

C++, 79 76 64 bytes

[](auto a,auto b){while(a<--b)*a%2?*++a:(*a^=*b,*b^=*a,*a^=*b);}

This function accepts a pair of iterators (which must be random access iterators), and steadily moves them towards each other. When a points to an odd number, it is advanced. Otherwise, a points to an even number; b is decremented, and iter_swap'ed with a. (We use XOR swap, which saves us having to include <algorithm> - or <utility> for std::swap).

There are unnecessary swaps when b points to an even number, but we're golfing, not squeezing efficiency!

Demo

auto f=[](auto a,auto b){while(a<--b)*a%2?*++a:(*a^=*b,*b^=*a,*a^=*b);};

#include <array>
#include <iostream>
int main()
{
    auto a = std::array{ 3,2,2,5,2,1,2 };

    f(a.begin(),a.end());

    for (auto i: a)
        std::cout << i << " ";
    std::cout << std::endl;
}

Non-competitive answer

The natural C++ method is std::partition, but that comes out at 83 bytes:

#include<algorithm>
[](auto a,auto b){std::partition(a,b,[](auto x){return x&1;});}
\$\endgroup\$
3
  • \$\begingroup\$ I believe that's 80 bytes, since you need a newline after the #include directive. My math sucks though^^. You can replace != with -, saving 1 byte. I like your approach, it's clever! \$\endgroup\$ Commented Jul 18, 2018 at 14:04
  • 1
    \$\begingroup\$ otherwise the iterators could pass each other without ever becoming equal. If you're using RandomAccessIterator, you can use while(a<b) if that's more convenient than a!=b using a @O.O.Balance's a-b version. \$\endgroup\$ Commented Jul 19, 2018 at 11:12
  • \$\begingroup\$ You can shorten the 83-byte answer a bit by replacing algorithm with regex: codegolf.stackexchange.com/a/150895 \$\endgroup\$ Commented Jul 21, 2018 at 19:22
10
\$\begingroup\$

Pyth, 4 3 bytes

-1 byte thanks to isaacg

iD2

Try it online!

crossed out 4 is still regular 4

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Nice, I had oiI2. \$\endgroup\$
    – Mr. Xcoder
    Commented Jul 18, 2018 at 6:01
  • 4
    \$\begingroup\$ How about iD2? \$\endgroup\$
    – isaacg
    Commented Jul 18, 2018 at 17:59
  • \$\begingroup\$ Alternate 3 byte solution: oi2 \$\endgroup\$
    – Sok
    Commented Jul 31, 2018 at 10:33
9
\$\begingroup\$

R, 30 24 bytes

(x=scan())[order(!x%%2)]

Try it online!

-6 bytes thanks to JayCe

\$\endgroup\$
7
  • \$\begingroup\$ Nice! you can do 26 bytes \$\endgroup\$
    – JayCe
    Commented Jul 18, 2018 at 14:02
  • \$\begingroup\$ 24 for full program \$\endgroup\$
    – JayCe
    Commented Jul 18, 2018 at 14:08
  • \$\begingroup\$ @JayCe facepalm golfing at 3am with a new baby is not optimal. Thanks! \$\endgroup\$
    – Giuseppe
    Commented Jul 18, 2018 at 14:24
  • 6
    \$\begingroup\$ Congrats! A future Scratch golfer ? \$\endgroup\$
    – JayCe
    Commented Jul 18, 2018 at 14:34
  • 1
    \$\begingroup\$ My congrats also Giuseppe, as our Dr said to us, well done you have an expensive one :) \$\endgroup\$
    – MickyT
    Commented Jul 22, 2018 at 7:07
8
\$\begingroup\$

J, 5 bytes

\:2&|

Try it online!

\: sort descending by

2&| mod-2

\$\endgroup\$
2
  • \$\begingroup\$ Nice to see you coming over to the dark side... \$\endgroup\$
    – Jonah
    Commented Feb 5, 2019 at 21:19
  • \$\begingroup\$ @Jonah I had a weak moment. \$\endgroup\$
    – Adám
    Commented Feb 5, 2019 at 21:20
8
\$\begingroup\$

Japt, 2 bytes

ñv

Try it online!

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

Perl 6, 12 bytes

*.sort(*%%2)

Try it online!

Some Whatever code that sorts the input by parity, with odd numbers first. You can remove a % to get even numbers first instead. Note that 'Whatever' is the name of this sort of anonymous function.

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

MATL, 6 bytes

tog&)v

Try it on MATL Online

Alternately:

to_2$S

Try it on MATL Online

\$\endgroup\$
6
\$\begingroup\$

Haskell, 23 22 bytes

f odd<>f even
f=filter

Try it online! This is equivalent to

g x = filter odd x ++ filter even x

-1 byte thanks to Lynn


Other approaches:

(<>).($odd)<*>($even)$filter
import Data.List;sortOn even
g x=[i|m<-[0,1],i<-x,odd$m+i]
g x=[i|m<-[1,0],i<-x,mod i 2==m]
g x=id=<<filter<$>[odd,even]<*>[x]
\$\endgroup\$
3
  • \$\begingroup\$ But doesn't this need import Data.Semigroup? \$\endgroup\$
    – AlexJ136
    Commented Jul 18, 2018 at 8:56
  • 1
    \$\begingroup\$ @AlexJ136 As of GHC 8.4.1, (<>) is part of Prelude. As TIO still runs an older version, the import is needed there. But you're right, I should have mentioned this directly. \$\endgroup\$
    – Laikoni
    Commented Jul 18, 2018 at 9:02
  • 1
    \$\begingroup\$ k odd<>k even;k=filter saves a byte. \$\endgroup\$
    – lynn
    Commented Jul 18, 2018 at 10:27
5
\$\begingroup\$

Python 2, 37 36 bytes

lambda a:sorted(a,key=lambda x:~x%2)

Try it online!

1 byte tip o' the hat to Mr. Xcoder.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ ~ should work instead of 1-. \$\endgroup\$
    – Mr. Xcoder
    Commented Jul 18, 2018 at 6:01
  • \$\begingroup\$ @Mr. Xcoder: indeed, it does! \$\endgroup\$
    – Chas Brown
    Commented Jul 18, 2018 at 6:25
5
\$\begingroup\$

Stax, 5 bytes

{|eom

Run and debug it

Explanation:

{|eom Full program, implicit input
{  o  Sort by key:
 |e     Is odd?
    m Map over result:
        Implicit output with newline
\$\endgroup\$
5
\$\begingroup\$

Attache, 11 bytes

SortBy!Even

Try it online!

Explanation

Even returns true for even numbers and false otherwise. SortBy ranks false < true (by a numerical cast to 0 < 1), thus placing odd numbers before even ones.

\$\endgroup\$
5
\$\begingroup\$

JavaScript (Node.js), 29 bytes

a=>a.sort((a,b)=>(b&1)-(a&1))

Try it online! Save 4 bytes by only supporting positive values using b%2-a%2. If you write this as:

function(a){return a.sort((a,b)=>(b&1)-(a&1))}

then it will work on all sorts of old JavaScript implementations that didn't sort stably.

\$\endgroup\$
10
  • 1
    \$\begingroup\$ Doesn't a=>a.sort((a,b)=>b&1-a&1) work ? \$\endgroup\$ Commented Jul 18, 2018 at 11:43
  • 1
    \$\begingroup\$ @AlexisFacques No, that parses as b&(1-a)&1. \$\endgroup\$
    – Neil
    Commented Jul 18, 2018 at 13:56
  • 1
    \$\begingroup\$ a=>a.sort(a=>++a&1) is shorter :) \$\endgroup\$
    – Max
    Commented Jul 19, 2018 at 14:34
  • \$\begingroup\$ @Max It might work on the given test cases but I wouldn't be surprised if someone found an example where it doesn't work. \$\endgroup\$
    – Neil
    Commented Jul 19, 2018 at 14:42
  • 1
    \$\begingroup\$ @Max You might as well submit that as your own answer. \$\endgroup\$
    – Neil
    Commented Jul 19, 2018 at 14:47
5
\$\begingroup\$

T-SQL, 26 bytes

SELECT*FROM t ORDER BY~i&1

Uses the bitwise AND operator "&" to compare the last digit with 1.

EDIT: Bitwise NOT then shorter than adding 1. EDIT2: Reorder to allow removal of the space.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice! Beat me by 5! Save one more byte by swapping the order and dropping the space: ORDER BY~i&1 \$\endgroup\$
    – BradC
    Commented Jul 19, 2018 at 16:12
5
\$\begingroup\$

PHP, 55 bytes

~14 months later and I'm a little bit better at golfing now:

for(;''<$n=$argv[++$i];$s=$n%2?"$n $s":"$s $n");echo$s;

Try it online!


PHP (>=5.4), 84 82 bytes

(-2 bytes, thanks to Ismael Miguel)

<?array_shift($a=&$argv);usort($a,function($i){return$i%2==0;});echo join(' ',$a);

To run it:

php -n <filename> <number_1> <number_2> ... <number_n>

Example:

php -n sort_odds_first.php 2 0 1 -1 3 8 29 -666

Or Try it online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Instead of $a=array_slice($argv,1);, use array_shift($a=&$argv);, which saves 1 byte. Also, remove the space before $a in join(' ', $a), saving another byte. Also, PHP 5.3 gives different results. You should specify for which version of PHP this solution is for. \$\endgroup\$ Commented Jul 20, 2018 at 11:02
  • 1
    \$\begingroup\$ @IsmaelMiguel: Thanks for the array_shift idea and pointing out the space mistake. I'm not sure how did I miss the space :D I have added the PHP >= 5.4 in title as well. \$\endgroup\$
    – Night2
    Commented Jul 20, 2018 at 18:25
  • \$\begingroup\$ It is a common mistake. I actually was surprised by the array_shift when I tried it and worked. \$\endgroup\$ Commented Jul 20, 2018 at 19:08
4
\$\begingroup\$

Jelly, 3 bytes

ḂÞṚ

Try it online!

One of the more oft-wanted atoms seems to be an is-even one (which would make this 2 bytes), without it we must reverse I believe...

ḂÞṚ - Link: list of integers
 Þ  - sort by:
Ḃ   -   bit (least significant bit - i.e. 1 if odd 0 if even)
  Ṛ - reverse
\$\endgroup\$
4
\$\begingroup\$

JavaScript, 22 20 bytes

a=>a.sort(a=>!(a%2))

Try it online!

\$\endgroup\$
10
  • \$\begingroup\$ I think you can drop the parentheses around your third a. \$\endgroup\$ Commented Jul 18, 2018 at 11:04
  • \$\begingroup\$ Doesn't work if 0 is included in the array. \$\endgroup\$
    – Shaggy
    Commented Jul 18, 2018 at 11:19
  • \$\begingroup\$ That's wrong. js comparator doiesn't work in such way. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… \$\endgroup\$
    – Qwertiy
    Commented Jul 18, 2018 at 11:48
  • 2
    \$\begingroup\$ According to the ECMA specification, "If comparefn is not undefined and is not a consistent comparison function for the elements of this array (see below), the behaviour of sort is implementation-defined." This compare function is not consistent. So this is not a JavaScript answer, but it might be an answer for some particular JavaScript implementation, and you'd have to name which implementation. \$\endgroup\$ Commented Jul 18, 2018 at 13:33
  • 1
    \$\begingroup\$ I think this fails for [1,2,3,4,5,6,6,-1,-2,-3,-4]. JavaScript array.sort is weird. \$\endgroup\$
    – Chas Brown
    Commented Jul 18, 2018 at 20:18
4
\$\begingroup\$

Python, 35 bytes

lambda l:sorted(l,key=(-1).__pow__)

Try it online!

Sorts by the function x -> (-1)**x, which gives -1 for odd and 1 for even.

\$\endgroup\$
4
\$\begingroup\$

Prolog (SWI), 50 bytes

A+S:-predsort([X,Y,Z]>>(Y/\1>Z/\1,X= <;X= >),A,S).

Try it online!

-8 thanks to Jo King

\$\endgroup\$
1
  • \$\begingroup\$ 50 bytes using a lambda \$\endgroup\$
    – Jo King
    Commented Jun 22, 2023 at 2:43
3
\$\begingroup\$

Red, 42 bytes

func[a][sort/compare a func[n][n % 2 = 1]]

Try it online!

If we need to account for negative values:

Red, 43 bytes

func[a][sort/compare a func[n][n // 2 = 1]]

Try it online!

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

Husk, 4 bytes

↔Ö%2

Try it online!

Explanation

 Ö     sort input according to the result of the following function
  %2   modulo 2
↔      reverse result to get odd numbers to the front
\$\endgroup\$
3
\$\begingroup\$

Scala, 18 bytes

_.sortBy(_.+(1)%2)
\$\endgroup\$
3
\$\begingroup\$

C#, 23 bytes

i=>i.OrderBy(u=>u%2==0)

Quite straigt forward really: This basically converts the numbers to booleans, whilst true means that the number is even and false that it's odd. Because true is higher than false the even numbers appear first.

The formatted version looks like that:

i => i.OrderBy (u => u % 2 == 0)

And you can test it like that:

Console.WriteLine (string.Join (",", new Func <IEnumerable <int>, IEnumerable <int>> (
                                    i => i.OrderBy (u => u % 2 == 0)
                                ).Invoke (new [] {3, 2, 2, 2, 1, 2, 5, 5})));

Which results in the following:

3,1,5,5,2,2,2,2
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Try it online! \$\endgroup\$
    – Neil
    Commented Jul 19, 2018 at 18:58
3
\$\begingroup\$

JavaScript, 23 bytes

6 bytes shorter than @Neil's answer using the same language :D

a=>a.sort(n=>-(n&1)||1)

Explanation:

The function passed to sort only cares about the first parameter. If it is odd it returns -1 (the result of -(n&1)). Otherwise (when -(n&1) yields 0) it returns 1.

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ Commented Jul 19, 2018 at 22:47
3
\$\begingroup\$

JavaScript (Chrome v67) - 24 19 23 bytes

a=>a.sort(a=>!(a&1)-.5)

The use of &1 rather than Math.abs()%2 was stolen from @Neil. Thanks!

Thanks to @Shaggy for showing my hacky 19 byte solution wasn't valid. If anyone wants it:

Depends on how the browser handles a hacky return value of 0. Chrome v67, after 100000 iterations of random arrays never sorted it wrong. I'm very sure it works -- and it relies on the specific sort algorithm Chrome uses too, I believe. (It might work in other browsers, that's not the point)

a=>a.sort(a=>++a&1)

\$\endgroup\$
2
  • \$\begingroup\$ Welcome to PPCG :) This fails for input [-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19] in my Chrome 67 console, outputting [7,-5,-3,17,-1,15,1,13,3,11,5,9,2,19,14,-4,6,18,-2,16,0,10,8,12,4]. \$\endgroup\$
    – Shaggy
    Commented Jul 20, 2018 at 9:07
  • \$\begingroup\$ @Shaggy -- oops! you're absolutely right! \$\endgroup\$
    – Max
    Commented Jul 20, 2018 at 10:21
3
\$\begingroup\$

JavaScript, 21 bytes

a=>a.sort(n=>(-1)**n)

Try it online

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

PowerShell, 22 19 bytes

$args|sort{!($_%2)}

Try it online!

Takes input via splatting, e.g., $a=(3,4,3); .\sort-odd-numbers-first.ps1 @a, which on TIO manifests as separate arguments for each entry.

Like some other answers here, Sort-Object can compare based on an expression. Here the expression is !($_%2), i.e., odds get sorted to $false and evens get sorted to $true. Thanks to how Boolean values are compared, falsey values are sorted first. This moves the odds to the beginning of the output, and the evens to the end. Sort-Object is stable, so the ordering of the individual items in their respective categories doesn't change (as in the TIO example).

-3 bytes thanks to mazzy.

\$\endgroup\$
3
  • \$\begingroup\$ It can to use a splatting. For example $a=(3,4,3); .\sort-odd-numbers-first.ps1 @a. So $args|sort{!($_%2)} is enough. Isn't it? \$\endgroup\$
    – mazzy
    Commented Jul 20, 2018 at 14:47
  • \$\begingroup\$ why "cheating"? it's native powershell feature. One more question: can we to use splatting inside codeGolf solution? for example, a solution contains several functions. if we can then why external call should not? if we cannot then why this feature banned? and what features are banned too? \$\endgroup\$
    – mazzy
    Commented Jul 20, 2018 at 18:31
  • 1
    \$\begingroup\$ @mazzy Thanks for pointing that out. I've updated my submission. \$\endgroup\$ Commented Jul 20, 2018 at 19:29
3
\$\begingroup\$

Ruby, 23 bytes

->a{a.sort_by{|i|~i%2}}

Try it online!

Explanation:

sort_by sorts every number as if its value were the result of the block (~i%2)

~x is equivalent to -x-1 and takes precedence over %2

Odd numbers will evaluate to 0 and even numbers will evaluate to 1 so odd numbers will be sorted first.

Barely related: this works on ruby from homebrew 2.5.1p57 (because it's based on a small bug) but only for non-negative integers, 20 bytes

->a{a.sort{|i|i%-2}}

Explanation:

This uses sort which expects a block that takes 2 values and returns -1, 0 or 1 depending on whether the first one is bigger, they're equal or the second one is bigger.

The block given here ignores the second value and returns -1 if the first number is odd or 0 if it's even.

It's not guaranteed to work but it does in some (I think buggy) implementations.

\$\endgroup\$
2
  • \$\begingroup\$ We define languages by their implementation here so your 20 byte solution is valid. \$\endgroup\$
    – Shaggy
    Commented Jul 18, 2018 at 11:17
  • \$\begingroup\$ @Shaggy Never mind, I had messed up my testing yesterday. \$\endgroup\$ Commented Jul 19, 2018 at 9:30
3
\$\begingroup\$

6502 machine code routine, 47 bytes

A0 00 84 FE B1 FB 4A 90 07 C8 C4 FD F0 20 D0 F4 2A 85 02 84 FE A4 FD 88 C4 FE
F0 12 B1 FB 4A 90 F6 2A AA A5 02 91 FB A4 FE 8A 91 FB 90 D6 60

Expects a pointer to an array of numbers in $fb/$fc and the length of this array in $fd. Manipulates the array in place to have all odd numbers in front. This is position independent code, so no load address is needed.

As the 6502 is an 8bit chip (so the instructions only deal with 8bit values, optionally signed), the valid number range is [-128 .. 127] and the maximum array size is 256.

Commented disassembly

; function to "partially sort" array, so all odd numbers come before all
; even numbers.
;
; input:
;   $fb/$fc: address of array to sort
;   $fd:     length of array to sort, 0 means 256 (maximum size)
;
; clobbers:
;   $fd/$fe: position from back/front of array
;   $2:      temporary for exchanging two values
;   A, X, Y

 .oddfirst:
A0 00       LDY #$00            ; initialize index from front
84 FE       STY $FE             ; to 0

 .search_front:
B1 FB       LDA ($FB),Y         ; load number from front
4A          LSR A               ; check for even/odd by shifting
90 07       BCC .search_back    ; if odd -> to searching from back
C8          INY                 ; next position from front
C4 FD       CPY $FD             ; same as position searching from back?
F0 20       BEQ .done           ; then we're finished
D0 F4       BNE .search_front   ; else check next from front
 .search_back:
2A          ROL A               ; shift carry back in
85 02       STA $02             ; and save number to temp
84 FE       STY $FE             ; save index from front
A4 FD       LDY $FD             ; load index from back
 .sb_loop:
88          DEY                 ; previous position from back
C4 FE       CPY $FE             ; same as position searching from front?
F0 12       BEQ .done           ; then we're finished
B1 FB       LDA ($FB),Y         ; load number from back
4A          LSR A               ; check for even/odd by shifting
90 F6       BCC .sb_loop        ; if odd -> check previous position
2A          ROL A               ; shift carry back in
AA          TAX                 ; remember in X
A5 02       LDA $02             ; load temporary from front
91 FB       STA ($FB),Y         ; store at current position
A4 FE       LDY $FE             ; load index from front
8A          TXA                 ; load remembered number
91 FB       STA ($FB),Y         ; store at current position
90 D6       BCC .search_front   ; and back to searching from front
 .done:
60          RTS

Example C64 assembler program using the routine:

Online demo

screenshot

Code in ca65 syntax:

.import oddfirst ; link with routine above

.segment "BHDR" ; BASIC header
                .word   $0801           ; load address
                .word   $080b           ; pointer next BASIC line
                .word   2018            ; line number
                .byte   $9e             ; BASIC token "SYS"
                .byte   "2061",$0,$0,$0 ; 2061 ($080d) and terminating 0 bytes

.bss
linebuf:        .res    5               ; maximum length of a valid signed
                                        ; 8-bit number input
convbuf:        .res    3               ; 3 BCD digits for signed 8-bit
                                        ; number conversion
numbers:        .res    $100            ; maximum array size that can be
                                        ; directly handled with indexing
                                        ; instructions

.data
prompt:         .byte   "> ", $0
message:        .byte   $d, $d, "Enter one number per line.", $d
                .byte   "just press enter (empty line) when done.", $0
errmsg:         .byte   "Error parsing number, try again.", $d, $0

.code
                lda     #$17            ; set upper/lower mode
                sta     $d018

                lda     #0
                sta     $2a             ; index for number array
                sta     $52             ; flag that at least one number was
                                        ; entered

                lda     #<message       ; display message
                ldy     #>message
                jsr     $ab1e

inputloop:
                lda     #<prompt        ; display prompt
                ldy     #>prompt
                jsr     $ab1e

                lda     #<linebuf       ; read string into buffer
                ldy     #>linebuf
                ldx     #5
                jsr     readline

                lda     linebuf         ; empty line?
                beq     process         ; -> start processing

                lda     #<linebuf       ; convert input to int8
                ldy     #>linebuf
                jsr     toint8
                bcc     numok           ; successful -> store number
                lda     #<errmsg        ; else show error message and repeat
                ldy     #>errmsg
                jsr     $ab1e
                bcs     inputloop

numok:          ldx     #$ff            ; set flag that we have a number
                stx     $52
                ldx     $2a
                sta     numbers,x
                inc     $2a             ; next index
                bne     inputloop       ; if array not full, next input

process:        lda     $52             ; check we have some numbers
                beq     exit            ; otherwise exit program

                lda     #<numbers       ; address of array to $fb/fc
                sta     $fb
                lda     #>numbers
                sta     $fc
                lda     $2a             ; length of array to $fd
                sta     $fd
                jsr     oddfirst        ; call "sorting" function

                lda     #$0             ; index variable for output loop
                sta     $52
outloop:        ldy     $52             ; load current index
                lda     numbers,y       ; load current number
                jsr     printnum        ; -> output
                inc     $52             ; next index
                lda     $52             ; compare with ...
                cmp     $2a             ; ... array size
                bne     outloop         ; not reached yet -> repeat

exit:           rts                     ; done, exit program

; read a line of input from keyboard, terminate it with 0
; expects pointer to input buffer in A/Y, buffer length in X
.proc readline
                dex
                stx     $fb
                sta     $fc
                sty     $fd
                ldy     #$0
                sty     $cc             ; enable cursor blinking
                sty     $fe             ; temporary for loop variable
getkey:         jsr     $f142           ; get character from keyboard
                beq     getkey
                sta     $2              ; save to temporary
                and     #$7f
                cmp     #$20            ; check for control character
                bcs     checkout        ; no -> check buffer size
                cmp     #$d             ; was it enter/return?
                beq     prepout         ; -> normal flow
                cmp     #$14            ; was it backspace/delete?
                bne     getkey          ; if not, get next char
                lda     $fe             ; check current index
                beq     getkey          ; zero -> backspace not possible
                bne     prepout         ; skip checking buffer size for bs
checkout:       lda     $fe             ; buffer index
                cmp     $fb             ; check against buffer size
                beq     getkey          ; if it would overflow, loop again
prepout:        sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
output:         lda     $2              ; load character
                jsr     $e716           ;   and output
                ldx     $cf             ; check cursor phase
                beq     store           ; invisible -> to store
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and show
                ora     #$80            ;   cursor in
                sta     ($d1),y         ;   current row
                lda     $2              ; load character
store:          cli                     ; enable interrupts
                cmp     #$14            ; was it backspace/delete?
                beq     backspace       ; to backspace handling code
                cmp     #$d             ; was it enter/return?
                beq     done            ; then we're done.
                ldy     $fe             ; load buffer index
                sta     ($fc),y         ; store character in buffer
                iny                     ; advance buffer index
                sty     $fe
                bne     getkey          ; not zero -> ok
done:           lda     #$0             ; terminate string in buffer with zero
                ldy     $fe             ; get buffer index
                sta     ($fc),y         ; store terminator in buffer
                sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
                inc     $cc             ; disable cursor blinking
                cli                     ; enable interrupts
                rts                     ; return
backspace:      dec     $fe             ; decrement buffer index
                bcs     getkey          ; and get next key
.endproc

; print an int8 number to the screen
; input:
;   A - the number to print
; clobbers:
;   X, Y
.proc printnum
                bpl     doprint         ; positive? -> direct number output
                eor     #$ff            ; else invert, 
                sta     $2              ; ...
                inc     $2              ; add one,
                lda     #'-'            ; output a minus sign
                jsr     $e716
                lda     $2
doprint:        tax                     ; number to X reg
                lda     #$0             ; set A to 0
                jsr     $bdcd           ; routine for uint16 in X/A output
                lda     #' '            
                jmp     $e716           ; and print a space
.endproc

; parse / convert int8 number using a BCD representation and double-dabble,
; handle negative numbers.
.proc toint8
                sta     $fb
                sty     $fc
                ldy     #$0
                sty     $fd
                sty     $fe
                sty     convbuf
                sty     convbuf+1
                sty     convbuf+2
scanloop:       lda     ($fb),y
                beq     copy
                iny
                cmp     #$20
                beq     scanloop
                cmp     #$2d
                beq     minus
                cmp     #$30
                bcc     error
                cmp     #$3a
                bcs     error
                inc     $fd
                bcc     scanloop
minus:          lda     $fd
                bne     error
                lda     $fe
                bne     error
                inc     $fe
                bne     scanloop
error:          sec
                rts
copy:           dey
                bmi     error
                ldx     #$2
copyloop:       lda     ($fb),y
                cmp     #$30
                bcc     copynext
                cmp     #$3a
                bcs     copynext
                sec
                sbc     #$30
                sta     convbuf,x
                dex
copynext:       dey
                bpl     copyloop
                lda     #$0
                sta     $fb
                ldx     #$8
loop:           lsr     convbuf
                lda     convbuf+1
                bcc     skipbit1
                ora     #$10
skipbit1:       lsr     a
                sta     convbuf+1
                lda     convbuf+2
                bcc     skipbit2
                ora     #$10
skipbit2:       lsr     a
                sta     convbuf+2
                ror     $fb
                dex
                beq     done
                lda     convbuf
                cmp     #$8
                bmi     nosub1
                sbc     #$3
                sta     convbuf
nosub1:         lda     convbuf+1
                cmp     #$8
                bmi     nosub2
                sbc     #$3
                sta     convbuf+1
nosub2:         lda     convbuf+2
                cmp     #$8
                bmi     loop
                sbc     #$3
                sta     convbuf+2
                bcs     loop
done:           lda     $fe
                beq     positive
                lda     #$ff
                eor     $fb
                sta     $fb
                inc     $fb
positive:       lda     $fb
                clc
                rts
.endproc
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Extended), 9 bytes

-7 thanks to @rak1507.

{⍵[⍒2|⍵]}

Explanation:

{⍵[⍒2|⍵]}
    2|⍵      ⍝ ⍵ mod 2, return 1 for each odd element and 0 for each even element
   ⍒         ⍝ pick the indices that produce the array sorted in descending order
  [    ]     ⍝ pick elements corresponding to indices in provided order...
 ⍵           ⍝ from ⍵

For example:

2|6 7 8 9        => 0 1 0 1
⍒0 1 0 1         => 2 4 1 3
6 7 8 9[2 4 1 3] => 7 9 6 8

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ {⍵[⍒2|⍵]} I think this works \$\endgroup\$
    – rak1507
    Commented Dec 20, 2020 at 21:11

Your Answer

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

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