5
\$\begingroup\$

I have this code :

tr ' ' '\n'|sort -n|head -1

The code is pretty simple, it takes a list of integer in the standard input stream (like 5 9 8 7 5 2 -12 -30), it sort the integers and display only the first integer. But i need to ouput 0 if the given list is empty. And i can't find a short way to that. I have a solution with a ternary operator and a echo 0, but i feel i can do far better. I just need to replace the input stream by 0 if this stream is empty.

Sidenote : I don't need to call read to get the user input. The program is called with the input stream directly like cmd < 1 5 6 -20 45

Here my current code :

read l
[ -n "$l" ]&&echo $l|tr ' ' '\n'|sort -n|head -1||echo 0
\$\endgroup\$
8
  • \$\begingroup\$ @Pietu1998 i added my current code \$\endgroup\$
    – Magus
    Feb 15, 2016 at 13:16
  • \$\begingroup\$ In this case you can cheat by always outputting a 0 first, if leading zeroes are allowed. \$\endgroup\$
    – orlp
    Feb 15, 2016 at 13:47
  • \$\begingroup\$ @orlp nice thinking but sadly leading zeroes are not allowed \$\endgroup\$
    – Magus
    Feb 15, 2016 at 13:59
  • \$\begingroup\$ This looks like a programming problem to go on Stack Overflow. I'm not sure though; I haven't done any action on the question in terms of close/up/down voting. \$\endgroup\$
    – hyper-neutrino
    Feb 15, 2016 at 19:40
  • \$\begingroup\$ @AlexL. Make code X shorter will be very poorly received on Stack Overflow. \$\endgroup\$
    – Dennis
    Feb 15, 2016 at 19:41

4 Answers 4

5
\$\begingroup\$

34 bytes

a=($(tr \  \\n|sort -n))
echo $[a]

The first line saves the sorted input values in an array a.

This avoids using head -1, since referencing the array as $a will yield its first value.

The second line uses a in the arithmetic expansion $[a]. In this context, an empty string is interpreted as 0.

For a different default value, parameter substitution could be used instead. For example, the last line could become

echo ${a:-puppies}
\$\endgroup\$
4
\$\begingroup\$

37 33 32 bytes

tr \  \\n|sort -n|sed s/^$/0/\;q

Edit: Saved 4 bytes thanks to @DigitalTrauma.

\$\endgroup\$
5
  • \$\begingroup\$ sed 1q is one shorter than head -1. Then you can combine the sed expressions to get 33 bytes: tr \ \\n|sort -n|sed s/^$/0/\;1q \$\endgroup\$ Feb 15, 2016 at 17:57
  • 1
    \$\begingroup\$ @DigitalTrauma Am I overlooking something or does sed q work? \$\endgroup\$
    – Neil
    Feb 15, 2016 at 19:24
  • \$\begingroup\$ yes - even better! \$\endgroup\$ Feb 15, 2016 at 19:25
  • \$\begingroup\$ @DigitalTrauma @Neil The sed script can be shortened by 1 byte further using /./q\;c\0 as long as the empty list doesn't contain white spaces. \$\endgroup\$
    – seshoumara
    Aug 29, 2016 at 14:48
  • 1
    \$\begingroup\$ tr \ \\n -> fmt -1 \$\endgroup\$
    – user98766
    Oct 17, 2020 at 4:11
1
\$\begingroup\$

42 bytes

Two different ways that have the same byte-count Use awk as the last command

tr ' ' '\n'|sort -n|awk 'NR==1{print $1+0}'

Or do all the computations in awk

awk -v RS=" " '{m=m>$1?m:$1}END{print m+0}'
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I could shrink the all in awk version by a couple bytes using awk -v RS=" " '$1>m{m=$1}END{print m+0}', but then the two versions would have different byte-counts. :p \$\endgroup\$ Feb 15, 2016 at 15:08
1
\$\begingroup\$

Pure : 41 bytes.

No requirement of any tr, sort, head...

t=${1:-0};for i;{ ((t=i<t?i:t));};echo $t

In a function you could use local -i for integer variables:

f() { local -i t=$1;for i;{ ((t=i<t?i:t));};echo $t;}

Then

f 5 9 8 7 5 2 -12 -30
-30

f
0

Note: If you need to read them from stdin

read l
f $l

will do the job.

As:

read l;for i in ${l:-0};{ ((t=i<t?i:t));};echo $t;}

Another version 58 bytes.

Something longer, but could be quicker, as there is no loop.

. <(printf v[%d+99**9]=\  $@);v=(${!v[@]});echo $[v-99**9]

In a function:

f() { local v;. <(printf v[%d+99**9]=\  $@)
      v=(${!v[@]});echo $[v-99**9];}

Then

f 34 56 1000 12  -156 53 -12 -21 321 3221
-156

f
0
\$\endgroup\$

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.