LL Golf Hole 5 - 最上位の桁を数え上げる
Posted feedbacks - Flatten
Nested Hiddenちょっと不格好かなぁ…。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <iostream>
void count(int n)
{
int d = 1;
int i = 0;
while(i <= n)
{
std::cout << i << std::endl;
i += d;
if((i / (d * 10) > 0))
{
d *= 10;
}
}
}
int main(int, char* [])
{
count(300);
return 0;
}
|
引数。
1 2 3 4 5 6 7 8 | echo 0
while :;do
for ((i=1;i<10;i++));do
echo $i$m
[ $i$m = $1 ]&&exit
done
m=${m}0
done
|
SWI-Prologで。
1 2 3 4 | count(N) :- writeln(0), sub_atom(N,1,_,_,Y), between(1,9,X),
atom_concat(X,Y,XY), writeln(XY), atom_number(XY,N), !.
:- count(300).
|
コマンドを呼ぶと28B。
1 | seq 0 300|grep '^[1-9]\?0*$'
|
問題例のスクリプト f(300)の場合は、うまくいくけど f(310)とか一般的な場合にうまくいかないと思うけど。
1 2 3 | count n = takeWhile (<= n) (0:[x*n | n <- [10^n|n<-[0..]], x <- [1..9]])
main = mapM_ print $ count 300
|
Squeak Smalltalk で。
1 2 3 4 5 6 7 | | n m |
n := 300.
m := 0.
World findATranscript: nil.
[m <= n] whileTrue: [
Transcript cr; show: m.
m := m + (10 raisedTo: m asString size - 1)]
|
1 | (do((a 1)(e(read)))((< e(incf a(expt 10(floor(log(print a)10)))))))
|
grepが一番シンプルかもですね。
1 | count <- function(n) grep("^[0-9]0*$", 0:n, value=T)
|
perl countup.pl 300
1 2 3 4 5 6 7 | while($ARGV[0]>=($x=$n++ . '0' x $c)){
print "$x\n";
if($n == 10){
$n=1;
$c++;
}
}
|
たしかに。grepを使ったらシンプルに。
1 | ruby -e 'p (0..300).collect{|i| i.to_s}.grep(/^[1-9]?0*$/)'
|
("0".."300")という書き方ができるんですね。そうすればcollectの部分も不要。投稿してから気がつきました。
Javaだとこんなもんでしょうか?
1 2 3 4 5 6 7 8 | class LL_Golf_Hole_5 {
public static void main(String[] args) {
for(int i=0; i<=Integer.parseInt(args[0]); i++) {
if(String.valueOf(i).charAt(0) != String.valueOf(i-1).charAt(0) )
System.out.println(i);
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 | module Main where
import Control.Arrow
import System.Environment
funcA = arr ((head >>> read >>> (>=) >>> takeWhile) &&& const lst)
>>> arr (app >>> (:) 0)
>>> Kleisli (mapM_ print)
where lst = concat $ iterate (map (10*)) [1..9]
main = getArgs >>= runKleisli funcA
|
標準入力。
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/sed -nf
x
:a
s/$/0/
:b
p
G
/^\(.*\)\n\1$/b
s/\n.*//
/^9/{s//1/;ba}
y/12345678/23456789/
s/^0/1/
bb
|
1 2 3 4 5 6 7 | #!/usr/bin/env python
# -*- coding: utf8 -*-
def f(n, m=0):
print m
return (n == m) and True or f(n, m + 10 ** (len(str(m)) - 1))
f(300)
|
余り面白く無いかも知れませんが,範囲演算子とgrepを使って書いてみました。
1 | print join("\n",grep{/^\d0*$/}0..$ARGV[0])
|
数値に限定されるのでもう少し簡単な正規表現で書けます。
1 | seq 0 300|grep '^.0*$'
|
1 2 3 4 5 6 7 8 9 | function f(n) {
var m = 0, r = [];
while (n >= m) {
r.push(m);
m += Math.pow(10, (("" + m).length - 1));
}
return r;
}
alert(f(300).join("\n"));
|
while文を1行にした。
1 2 3 4 5 6 | function f(n) {
var m = 0, r = [m];
while (n >= (m += Math.pow(10, (("" + m).length - 1)))) r.push(m);
return r;
}
alert(f(300).join("\n"));
|
コマンドラインからで67バイト。
1 | puts z=0;while 1.upto(9){|i|puts((t=i*10**z)<=300?t:exit)};z+=1;end
|
標準入力に対応させてみました
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream>
#include <cstdlib>
#include <cstring>
void func(int m, int n = 0)
{
char buf[BUFSIZ];
int i = 1;
int size = ::strlen(::itoa(n, buf, 10)) - 1;
std::cout << n << std::endl;
while(size--) i *= 10;
if(m > n) return func(m, n+i);
}
int main(int argc, char* argv[])
{
argc == 2 ? func(::atoi(argv[1])) : func(300);
}
|
取り敢えずパッと思い付いたのを。
1 2 | import Data.List
main=readLn>>=print.(\n->fst$span(<=n)$nub$concat$iterate(map(*10))[0..9])
|
余り短く出来ませんでしたが...。
1 2 3 4 | object M{
def c(d:Int,f:Int,m:Int):Unit=if(d*f<=m){printf("%d\n",d*f);c(d%9+1,f*(1+9*(d/9)),m)}
def main(a:Array[String])=c(0,1,Integer.parseInt(a(0)))
}
|
1 2 3 4 5 6 7 | class Program {
static void Main(string[] args) {
for (int i = 0; i <= int.Parse(args[0]); i++)
if (System.Text.RegularExpressions.Regex.IsMatch(i.ToString(), "^.0*$"))
System.Console.WriteLine("{0}", i);
}
}
|
たしかに、数値しか入力されないから"."で十分なのですね。シンプルすぎる・・・
1 | grep("^.0*$",0:300)-1
|
1 | using System;class P{static void Main(string[]a){for(int i=0;i<=int.Parse(a[0]);i++)if(i%Math.Pow(10,i.ToString().Length-1)==0)Console.WriteLine(i);}}
|
nubだと遅いので。。。
1 | main=readLn>>=print.(0:).fst.flip span(concat$iterate(map(10*))[1..9]).(>=)
|
皆さんのご意見を元に改良。
コマンドラインから上限を得ます。
1 | puts ("0"..ARGV[0]).grep(/^.?0*$/)
|
> また、与えられる自然数には0以外の桁が2回以上登場してはいけません。
という条件付です~。
XPath の conditional expressions(if then else) など使ってみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
>
<xsl:output method="text" />
<xsl:variable name="goal" as="xs:string" select="'300'" />
<xsl:template match="/" >
<xsl:variable name="digit" as="xs:integer" select="fn:string-length($goal)" />
<xsl:for-each select="1 to $digit">
<xsl:variable name="d" as="xs:integer" select="." />
<xsl:for-each select="(if (.=1) then 0 else 1)
to
(if (.=$digit) then xs:integer(fn:substring($goal,1,1)) else 9)" >
<xsl:value-of select="." />
<xsl:for-each select="2 to $d">
<xsl:value-of select="0" />
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
|
#7156さんのをもうちょっと短く。68bytes
1 | while($ARGV[0]>=($x=$n++.0 x$c)){print"$x\n";$n==10&&($n=1)&&$c++}
|
Javaで頑張って縮めてみました。 改行・タブを消して 146B
1 2 3 4 5 6 7 8 | class LL_Golf_Hole_5{
public static void main(String[]s){
for(int i=0,t=1;i<=Integer.parseInt(s[0]);i+=t){
System.out.println(i);
if(i==t*10)t*=10;
}
}
}
|
grepでもやってみる。40bytes
1 | $,="\n";print grep/^\d0*$/,0..$ARGV[0]
|
1 2 3 4 5 | def max = args[0].toInteger()
(0..max).collect{
def num = it.toString()
num[0] + "0" * (num.size()-1)
}.unique().each{ println it }
|
mattsanさんの#7145を参考に標準入力に対応しつつgolf化. 164bytes. 改行5,空白4省略可で実質155bytes 本当はoperator<()を定義してcout<cin とかやりたかったけど、短さを優先しました。
1 2 3 4 5 6 7 | #include<iostream>
using namespace std;
void f(ostream&o,istream&i){
int c=0,d=1,n;i>>n;
while(c<=n)o<<c<<"\n"&&(c+=d)&&c/d/10&&(d*=10);
}
main(){f(cout,cin);}
|
別関数に分けずにベタでmain内に書いたほうがよっぽど短かった orz というわけで元コードは自分で-1. 116btyes.実質109bytes
1 2 3 4 5 | #include<iostream>
main(){
int c=0,d=1,n;std::cin>>n;
while(c<=n)std::cout<<c<<"\n"&&(c+=d)&&c/d/10&&(d*=10);
}
|
データは標準入力から。
1 | exit wd"0(a&>:#])0,,(10x^i.#":a=.".}:1!:1[3)*/>:i.9
|
1 2 3 4 5 6 7 8 9 10 11 | (use srfi-1)
(define (main args)
(let ((n (string->number (cadr args))))
(print 0)
(let loop ((i 1))
(receive (xs ys) (partition (cut <= <> n)
(map (cut * i <>) '(1 2 3 4 5 6 7 8 9)))
(for-each print xs)
(if (pair? ys)
0
(loop (* i 10)))))))
|
ループより再帰の方がきれいに書けるかも?と思ったので試してみました。
もう少しうまく書けそうですが・・・
1 2 3 4 | count <- function(n=300){
if(n!=0) Recall(n - 10^(nchar(n-1)-1))
print(n)
}
|
80byte
1 2 | <?$m=fgets(STDIN);for($a=0;$a<=$m;eval('$a+=1e'.(strlen($a)-1).';'))echo$a,'
';
|
素直に書いた方が短いんですけどね。71byte
1 2 | <?$m=fgets(STDIN);for($a=0;$a<=$m;$a+=pow(10,strlen($a)-print$a.'
'));
|
正規表現をお借りして、43バイト。
1 | iで0から尋(i)まで繰返,RE(i,"^.0*$")なら表示
|
正規表現を使って短かく。 80 bytes。
1 | (use srfi-1)(for-each print(filter(compose #/^.0*$/ x->string)(iota(+(read)1))))
|
1 | x=[1..9]++(map(10*)x);main=readLn>>=print.fst.(`span`(0:x)).(>=)
|
C++に対抗意識を燃やしてみたけどかてなかったorz
うーん、atoi()をstrcmp()にすればもう少し短くなる気がするんだけどうまく動かない。。
strcmp()って短い文字列は小さいと判断されると思ったのだけど気のせいかなー?
// gcc -Wall doukaku200.c
ちなみに圧縮すると↓のような感じ(113バイト?)
char s[9]={48},*t=s;
main(int ac, char* av[]){for(;atoi(s)<atoi(av[1]);(*s)++)
{puts(s);if(*s==59)*s=*(++t)=48;}}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h>
#include <stdlib.h>
char s[9]={0x30},*t=s;
int main(int ac, char* av[])
{
for(;atoi(s)<=atoi(av[1]);(*s)++)
{
puts(s);
if(*s==0x39)
{
t++;
*s = *t = 0x30;
}
}
return 0;
}
/* EOF */
|
修正みすってるorz
char s[9]={0x30},*t=s;
↓
char s[9]={0x31},*t=s;
もう若干短く出来ました。
1 | map{print"$_\n"if/^.0*$/}0..$ARGV[0]
|
"の方が微妙に短いようですね。
1 | <?for($a=0;$a<=$argv[1];$a+=pow(10,strlen($a)-print"$a "));
|
powを使った方が短いようですが一応載せてみます。
1 | <?for($a=0;$a<=$argv[1];)ereg('^.0*$',$a++,$m)&&print"$m[0] ";
|
スクリプト内のリテラルとして、300という整数を与えています。 escript スクリプトのファイル名 として実行します。 この場合、最初のコメント行は必須です。
1 2 3 4 5 | %
s(X,Y)when X < 10->erlang:display(Y);
s(X,Y)when X rem 10=:=0->s(X div 10,Y);
s(_,_)->0.
main(_)->[s(X,X)||X<-lists:seq(0,300)].
|
1 2 3 4 5 6 7 | def g(upto, n=0):
zeros, i = divmod(n, 9)
x = int(str(i+1) + '0'*zeros)
print x
if x < upto:
g(upto, n+1)
g(300)
|
#7164をお手本にバッチで。(ワンライナーで76バイトですが、実行速度は遅いです。)
e.g.
C:\>@echo off & (for /l %i in (0,1,300) do echo %i|findstr /r "^.0*$") & echo on
正規表現だと一瞬だ・・・
1 2 | def max = args[0].toInteger()
(0..max).findAll{ it =~ /^.0*$/ }.each{ println it }
|
1 | main=do n<-readLn;print$filter(all(<'1').tail.show)[0..n]
|
縦と横のマトリックス風。
1 2 3 4 5 6 7 8 9 | def h(n, m=0, z=""):
print m
for i in n[::-1]:
m = 10 if int(i)==0 else int(i)+1
for j in range(1, m):
print str(j) + z
z += i
h("300")
|
MySQL と oracle で動作を確認しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | SELECT DISTINCT t.x*v.y count_up
FROM (
SELECT 0 x FROM DUAL UNION
SELECT 1 FROM dual UNION
SELECT 2 FROM dual UNION
SELECT 3 FROM dual UNION
SELECT 4 FROM dual UNION
SELECT 5 FROM dual UNION
SELECT 6 FROM dual UNION
SELECT 7 FROM dual UNION
SELECT 8 FROM dual UNION
SELECT 9 FROM dual) t
, (SELECT 1 y FROM dual UNION
SELECT 10 FROM dual UNION
SELECT 100 FROM dual UNION
SELECT 1000 FROM dual UNION
SELECT 10000 FROM dual UNION
SELECT 100000 FROM dual UNION
SELECT 1000000 FROM dual UNION
SELECT 10000000 FROM dual UNION
SELECT 100000000 FROM dual UNION
SELECT 1000000000 FROM dual UNION
SELECT 10000000000 FROM dual UNION
SELECT 100000000000 FROM dual UNION
SELECT 1000000000000 FROM dual) v
WHERE t.x*v.y <= 300
ORDER BY t.x*v.y;
|
正規表現版、Rubyの回答を参考にしました。
1 | (0..300).each{ans->if(ans.toString()==~'[0-9]0*') println ans}
|
1 | javascript:for(a=[i='0'];i<300;)a.push(i=++i[0]+i.slice(1));a
|
ゴルフらしく。
1 | (0..300).grep(~/.0*/).any 0.&println
|
1 | javascript:for(a=[i=0];i<300;)a[/^.0*$/(++i)]=i;a
|
1 | (dotimes(i(+ 300 1))(if(#/^.0*$/#`",i")(print i)))
|
old awkです。 ほぼそのままC言語のコードになっちゃいました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!awk -f
{
max=$1
print 0
for(b=1;;b*=10) {
n=b
for(j=10;--j>0;n+=b) {
if(n>max) next
print n
}
}
}
|
コマンドラインで数を指定します。 int/longの範囲を超える大きな数値でもOK.数値ではなく文字列処理でやってるんで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h>
int main(int argc, char *argv[])
{
char *p, *q;
int len;
len=strlen(argv[1]);
p=malloc(len+1);
memset(p, ' ', len);
p[len]='\0';
q=p+len-1;
*q='0' -1;
while(strcmp(argv[1], p)>0) {
if(++(*q) >'9') {
*q='0';
*--q ='1';
}
puts(q);
}
}
|
標準入力から。
この手の文字列操作はガーベジコレクタのおかげでたやすくできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import std.stdio, std.string;
void main() {
auto t = chomp(readln), s = "0".dup;
while(s.length < t.length || s <= t) {
writeln(s);
if(s[0] < '9') {
s[0]++;
} else {
s = "10" ~ s[1 .. $];
}
}
}
|
行数・バイト数のgolfは諦めて、ステップ数で・・・ 桁数と最上位の数がわかれば、繰り返し毎の 与えられた数との比較を省けるはずです。
TODO: itertools.chainでジェネレータを連結 (多分、読みにくくなるだけ TODO: (10**x) も、もう一段階外側に追い出せる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import math
def count_up(num):
assert num > 0
n = int(math.floor(math.log10(num)))
m = int(num / (10**n))
yield 0
for i in xrange(n):
for j in xrange(1,10):
yield (10**i)*j
for _ in xrange(1):
for j in xrange(1,m+1):
yield (10**n)*j
if __name__ == '__main__':
for n in count_up(300):
print n
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | (* 例解の *)
#load "nums.cma";;
open Num
let f =
let rec loop n m =
let s = string_of_num m in print_endline s;
if n<>m then loop n (m +/ (power_num (Int 10) (Int (String.length s - 1))))
in
fun n -> loop (Int n) (Int 0);;
(* f 300;; *)
(* 正規表現の *)
#load "str.cma";;
let f =
let reg = Str.regexp "^[0-9]?0*$" in
fun n -> Str.string_match reg (string_of_int n) 0;;
(* for i = 0 to 300 do (if f i then Printf.printf "%d\n" i) done;; *)
(* 自力の *)
let f n =
let rec loop next diff b =
if n<b then () else
if next>b then (Printf.printf "%d\n" b; loop next diff (diff + b)) else
loop (next*10) next b
in loop 10 1 0;;
|
39bytes
1 | for(0..$ARGV[0]){print"$_\n"if/^\d0*$/}
|
同じ発想でRuby
1 | "0".upto($*[0]){|$_|puts$_ if/^\d0*$/}
|
もうちょっと縮まった
1 | puts ("0"..$*[0]).grep(/^\d0*$/)
|
もうちょい縮みます。 32B 。まだなんかあるかも。
1 2 | print"$_
"x/^.0*$/for 0.."@ARGV"
|
あう、 "ARGV[0]" は pop で良い。 28B
1 2 | print"$_
"x/^.0*$/for 0..pop
|
Count down していく方が短くなりそう。 55B 。
1 2 3 4 5 6 7 8 | h
:
s/\n.*//
y/987654321/876543210/
s/^00/9/
G
h
/^0/!b
|
例のごとくひねりはありません。
表示すべき数字は文字列で生成してたりして、かなり卑怯な気がします(^^;。
scala h5.scala で実行します。
1 2 3 4 5 | val n=args(0).toInt
def p(i:Int,c:Int){
val v=(""+i+("0"*c)).toInt;if(v<=n){println(v);if(i<9)p(i+1,c)else p(1,c+1)}
}
p(0,0)
|
コンパイル時に /fast- を指定してください。
1 | for(i=-1;i++<300;)/^.0*$/.test(i)&&print(i)
|
100バイト切れた。 まだまだですがこんなところで。
1 2 3 4 5 | b=10;c;main(a){a=atoi(gets());while(a>=b){printf("%d\n",c);c+=b/10;c>=b?b*=10:1;}printf("%d\n",a);}
$> cat num.txt
100
$> cat num.txt | ./a.out
|
ごめんなさい。例題が上手くさばけてませんでした...。
b=10;c;main(a){a=atoi(gets());while(a>=c){printf("%dn",c);c+=b/10;c>=b?b*=10:1;}}
1 | というわけで修正してみました。大丈夫だと思いますが...。
|
VBA for Excel (2003)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Sub Main()
n = Val(InputBox(""))
m = 0
p = 0
Do
Range("A1").Offset(p) = m
If m = n Then
Exit Do
End If
l = Len(Str(m)) - 2
m = m + 10 ^ l
p = p + 1
Loop
End Sub
|
gets用のバッファが必要なのでは?? 修正+若干の縮め
1 | b=1;c;main(a){for(scanf("%d",&a);a>=c;c+=b,b*=c-b*10?1:10){printf("%d\n",c);}}
|
1 2 3 4 5 6 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 | #module
#deffunc CountUpMaxPlace var vIo, local c
c = peek(vIo)
if ( '0' <= c && c <= '8' ) {
poke vIo, , c + 1
} else : if ( c == '9' ) {
poke vIo,, '1'
vIo += "0"
} else {
vIo = "0"
}
return
#global
nMax = 300 // 数える最大値
sdim sBuf, 3200
sdim sNumber
repeat
CountUpMaxPlace sNumber
sBuf += sNumber +"\n"
if ( int(sNumber) >= nMax ) {
break
}
loop
objmode 2
mesbox sBuf, ginfo(12), ginfo(13)
stop
|






takano32
#7116()
[
Ruby
]
Rating1/3=0.33
与えられた自然数までの数え上げを行います。ただし、繰り上がりが起こったときは最上位の桁のみを数え上げます。また、与えられる自然数には0以外の桁が2回以上登場してはいけません。たとえば、300を入力として与えられた場合は以下のような出力となります。
与える自然数についてはリテラルで与える、標準入力で与える、引数で与えるなどは自由とします。
※LL Future実行委員の高野光弘です。この出題は LL Future公式の出題であり、優れたものについてはLL Golfのセッションでご紹介させていただくかもしれません。ご理解の上、ご投稿ください。また、LL Futureのチケットは現在も発売中です。よろしければ、メインイベントの方にもぜひご参加ください。
Rating1/3=0.33-0+
[ reply ]