税込み価格への修正
Posted feedbacks - Flatten
Nested Hidden関数にはしていませんが…(^_^;)。
1 2 3 4 5 6 7 8 9 10 11 | | inString in out |
inString := 'ダイコン150円、ハクサイ120円、ジャガイモ30円'.
in := inString readStream.
out := String new writeStream.
[in atEnd] whileFalse: [
in peek isDigit
ifTrue: [out print: ((Integer readFrom: in) * 1.05) floor]
ifFalse: [out nextPut: in next]].
^out contents
"=> 'ダイコン157円、ハクサイ126円、ジャガイモ31円' "
|
まぁシンプルに。
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 33 34 35 36 37 38 | import java.math.BigDecimal;
public class ZeikomiHyoki {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(new ZeikomiHyoki().execute(args[i]));
}
}
public String execute(String string) {
StringBuffer buffer = new StringBuffer();
StringBuffer integralBuffer = new StringBuffer();
boolean flg = false;
for (int i = 0; i < string.length(); i++) {
if (48 <= (int) string.charAt(i) && (int) string.charAt(i) <= 57) {
if (!flg) {
flg = true;
integralBuffer = new StringBuffer();
}
integralBuffer.append(string.charAt(i));
} else {
if (flg) {
flg = false;
buffer.append(calc(integralBuffer.toString()));
}
buffer.append(string.charAt(i));
}
}
return buffer.toString();
}
private String calc(String string) {
System.out.println(string);
return new BigDecimal(string).multiply(new BigDecimal("1.05")).setScale(0, BigDecimal.ROUND_DOWN).toString();
}
}
|
身も蓋もないけど。
1 2 3 | function Convert2TaxedHandout(s) {
return s.replace(/[1-9][0-9]*/g, function(p) { return Math.floor(p * 1.05); });
}
|
1 | perl -pe 's/(\d+)/int $1*1.05/eg'
|
ruby でも gsub ですかね。
1 | % ruby -pe '$_.gsub!(/\d+/){|s| (s.to_i * 1.05).to_i}'
|
どなたかかエレガントなコードをお願いします><
1 2 3 | import re
def include_tax(s):
return re.sub('\d+', lambda m: str(int(int(m.group(0)) * 1.05)), s)
|
文字列に多バイト文字が来ることもあるんですよね? Rubyの場合はKCODEを指定してやるだけですが。
1 2 3 4 5 | <?php
function conv_with_tax($str) {
return mb_ereg_replace("(\d+)", "intval(1.05 * \\1)", $str, "e");
}
?>
|
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 | import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ExciseTax {
private double rate;
public ExciseTax(double rate) {
this.rate = 1.0 + rate;
}
public String includeTax(String string) {
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(string);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, calcTaxIncludedPrice(m.group()));
}
m.appendTail(sb);
return sb.toString();
}
private String calcTaxIncludedPrice(String price) {
return Long.toString((long)(Long.parseLong(price) * rate));
}
public static void main(String[] args) {
System.out.println(new ExciseTax(0.05).includeTax("ダイコン150円、ハクサイ120円、ジャガイモ30円"));
}
}
|
初めてcl-ppcreを使ってみました
1 2 3 4 5 6 7 8 9 | (require 'cl-ppcre)
(defun including-tax (string)
(cl-ppcre:regex-replace-all
"\\d+" string
(lambda (num) (format nil "~a" (floor (* (parse-integer num) 1.05))))
:simple-calls t))
;; CL-USER> (including-tax "ダイコン150円、ハクサイ120円、ジャガイモ30円")
;; "ダイコン157円、ハクサイ125円、ジャガイモ31円"
|
ノーマルモードで実行
1 | :%s!\(\d\+\)!\=submatch(0)*105/100!g
|
C# 2.0 (ECMA C# 3rd edition) 以降。呼び出すたびにRegExインスタンスが作成されるのは無駄なんですが。
1 2 3 4 5 6 7 8 9 10 | public static string PlusTax(string expression)
{
return new System.Text.RegularExpressions.Regex("[0-9]+").Replace(expression, delegate(Match m)
{
int price;
int.TryParse(m.Value, out price);
price = (price * 105) / 100;
return price.ToString();
});
}
|
1 2 3 | def add_tax(str)
str.gsub(/\d+/){($&.to_i * 1.05).to_i}
end
|
上の方の人と丸被りだった。orz 申し訳ない。
正規表現はやっぱり苦手だ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # -*- coding: utf-8 -*-
def toTaxStr(s):
out = ""
items = s.split("円")
for item in items[0:-1]:
kakaku = ""
while(len(item) and item[-1].isdigit()):
kakaku = item[-1] + kakaku
item = item[0:-1]
out += item
if len(kakaku):
out += str(int(int(kakaku)*1.05))
out += "円"
return out + items[-1]
sample_str = "ダイコン150円、ハクサイ120円、ジャガイモ30円"
print unicode(toTaxStr(sample_str),"utf-8")
|
(\d*円)を修正する問題だと勘違いしていたorz。
何で白菜が125円なんだろう。 浮動小数点の誤差?
何の工夫もなしに
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 33 34 35 | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char* tax(char* src,char* dest){
char *p;
char buf[256];
long price;
p=src;
dest[0]='\0';
while(*p){
if(isdigit(*p)){
price=strtol(p,&p,10);
price=price*105/100;
sprintf(buf,"%ld",price);
strcat(dest,buf);
}else{
strncat(dest,p,1);
p++;
}
}
return dest;
}
int main(){
char buf[256];
tax("ダイコン150円、ハクサイ120円、ジャガイモ30円",buf);
printf("%s\n",buf);
tax("PC150000円、車2000000円",buf);
printf("%s\n",buf);
return 0;
}
|
税課税により、桁数が上がっても問題ないようにしたはず。
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node Node;
struct node {
char *string;
Node *next;
};
char *zei(char *);
void split(Node *head, char *string);
int main()
{
char *result_string;
result_string = zei("ダイコン150円、ハクサイ120円、ジャガイモ30円");
printf("%s\n", result_string);
free(result_string);
result_string = zei("ほげ8888円、ぴよ9999円");
printf("%s\n", result_string);
free(result_string);
return 0;
}
char *zei(char *original)
{
Node list;
Node *iter;
Node *iter2;
int value;
int count;
char *result;
split(&list, original);
/* 税追加と文字数のカウント */
count = 0;
iter = &list;
while (iter->next != NULL) {
if (iter->string[0] >= '0' && iter->string[0] <= '9') {
sscanf(iter->string, "%d", &value);
sprintf(iter->string, "%d", (int)(value * 1.05));
}
count += strlen(iter->string);
iter = iter->next;
}
/* 連結 */
result = malloc(sizeof(char) * (count+1));
result[0] = '\0';
iter = &list;
while (iter->next != NULL) {
strcat(result, iter->string);
free(iter->string);
iter = iter->next;
}
iter = list.next;
while (iter->next != NULL) {
iter2 = iter;
iter = iter->next;
free(iter2);
}
free(iter);
return result;
}
void split(Node *head, char *string)
{
Node *now;
int count;
head->string = NULL;
head->next = NULL;
now = head;
count = 0;
while (*string != '\0') {
while (string[count] >= '0' && string[count] <= '9') {
count++;
if (string[count] == '\0')
break;
}
now->string = malloc(sizeof(char) * (count+1+1)); /* 桁上がり分 */
strncpy(now->string, string, count);
now->string[count] = '\0';
now->next = malloc(sizeof(Node));
now = now->next;
now->string = NULL;
now->next = NULL;
string = string + count;
count = 0;
if (*string == '\0')
break;
while (!(string[count] >= '0' && string[count] <= '9')) {
count++;
if (string[count] == '\0')
break;
}
now->string = malloc(sizeof(char) * (count+1));
strncpy(now->string, string, count);
now->string[count] = '\0';
now->next = malloc(sizeof(Node));
now = now->next;
now->string = NULL;
now->next = NULL;
string = string + count;
count = 0;
}
}
|
(including-tax "ダイコン150円、ハクサイ120円、ジャガイモ30円") =>"ダイコン157円、ハクサイ126円、ジャガイモ31円"
1 2 3 | (define (including-tax str)
(let ((rep (lambda (m) (x->integer (floor (* (string->number (m 0)) 1.05))))))
(regexp-replace-all #/\d+/ str rep)))
|
(included-tax "ダイコン150円、ハクサイ120円、ジャガイモ30円") =>"ダイコン157円、ハクサイ126円、ジャガイモ31円"
1 2 3 | (defun including-tax (str)
(let ((rep (lambda (m) (number-to-string (floor (* (string-to-number m) 1.05))))))
(replace-regexp-in-string "[0-9]+" rep str)))
|
回答済みだけど、メモ代わりに。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string s = "test100xyz400";
Console.WriteLine(ReplaceTax(s));
}
public static string ReplaceTax(string s)
{
return Regex.Replace(s, @"\d+", delegate(Match m)
{
return ((int)(int.Parse(m.Value) * 1.05)).ToString();
});
}
}
|
たしかに、120 * 1.05はちょうど126.0になるはずですね…
一瞬、投稿ミスで重複になってしまったのかと思ってしまいました(笑)
ちゃんとfloor使ってやってみる
1 | perl -MPOSIX -pe 's/(\d+)/floor($1*1.05)/eg'
|
C++のSTLを使ってみました。bcc32(5.5)で確認。
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <iostream>
#include <sstream>
#include <cctype>
#include <string>
#include <algorithm>
#include <functional>
std::string convert_do(const std::string& s)
{
std::istringstream sin(s);
int price;
sin >> price;
price *= 1.05;
std::ostringstream sout;
sout << price;
return sout.str();
}
struct isdigit : std::unary_function<char, bool>
{
bool operator()(char c) const
{
return std::isdigit(c);
}
};
std::string convert(const std::string& s)
{
std::string ret;
std::string::const_iterator beg = s.begin();
std::string::const_iterator end = s.end();
while (true)
{
std::string::const_iterator cur;
cur = std::find_if(beg, end, isdigit());
ret.append(std::string(beg, cur)); beg = cur;
if (beg == end)
{
break;
}
cur = std::find_if(beg, end, std::not1(isdigit()));
ret.append(convert_do(std::string(beg, cur))); beg = cur;
}
return ret;
}
int main()
{
std::cout << convert("Æ_ÆCÆRÆ“150‰~ÂAÆnÆNÆTÆC120‰~ÂAÆWÆÆÆKÆCÆ‚30‰~") << std::endl;
}
|
1 2 3 4 5 6 | function tax(text)
return string.gsub(text, "%d+",
function(amt)
return tostring(math.floor(amt * 1.05))
end)
end
|
浮動小数点数だと、100 * 1.05 => 105 のようにちょうど整数になったとき、計算誤差によっては104になってしまうかもしれないので、整数のままで処理するように修正。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | --- main.cpp.orig Wed Jul 11 15:03:27 2007
+++ main.cpp Wed Jul 11 15:01:35 2007
@@ -13,11 +13,9 @@
sin >> price;
- price *= 1.05;
-
std::ostringstream sout;
- sout << price;
+ sout << (price * 105 / 100);
return sout.str();
}
|
UTF-8の入力で確認。
他では文字化けするかもしれません。
1 2 3 4 5 6 7 8 9 10 | import Char
includeTax s = inText s
where inText [] = []
inText (x:xs) | isDigit x = inPrice xs [x]
| otherwise = x : inText xs
inPrice (x:xs) y | isDigit x = inPrice xs (y ++ [x])
inPrice xs y = tax y ++ inText xs
tax s = show $ floor $ 1.05 * read s
main = getContents >>= (putStr . includeTax)
|
誤差っぽいですね。Common Lispは分数が使えるので1.05→21/20に変えてみたら126になりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | module doukaku;
private import std.stdio;
private import std.string;
private import std.regexp;
char[] including_tax(char[] str) {
return sub(str, r"[0-9]+", delegate(RegExp re) {
long price = atoi(re.match(0));
return format("%d", price*21/20);
}, "g");
}
void main() {
writefln(including_tax("ダイコン150円、ハクサイ120円、ジャガイモ30円"));
}
|
実際には日本語でコケますが・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import scala.io._
import java.util.regex._
class ExtendedString(self:String) {
def gsub(reg:String)(f:(String)=>String) = {
val result = new StringBuffer
val m = Pattern.compile("\\d+").matcher(self)
while(m.find) m.appendReplacement(result, f(m.group))
m.appendTail(result)
result.toString
}
def taxed():String = {
gsub("\\d+"){x => (Integer.parseInt(x)*1.05).asInstanceOf[Int].toString}
}
}
implicit def string2ext(self:String) = new ExtendedString(self)
"ダイコン150円、ハクサイ120円、ジャガイモ30円".taxed
|
1 2 3 4 5 6 7 8 9 10 11 12 | 「ダイコン150円、ハクサイ120円、ジャガイモ30円」を税込み価格で表示
●税込み価格(原稿を)
箱とは配列
原稿を「円」で区切って反復
対象を「\d+$」で正規表現マッチ
価格はそれの1.05倍の整数部分
対象の「\d+$」を「{価格}円」へ正規表現置換
箱にそれを配列追加
箱を空で配列結合して戻す
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | open System;;
open System.Text.RegularExpressions;;
let yen:string = "円";;
let tax str =
let re = new Regex( "\d+" ^ yen ) in
let matches = Seq.to_list { for m in re.Matches( str ) -> m.ToString() } in
let getPrice (s:string) = Int32.Parse(s.Replace(yen, "")) in
let taxes s = ((getPrice s) * 105 / 100).ToString() ^ yen in
let rec replace (base:string) = function
| [] -> base
| m::ms -> replace (base.Replace(m,(taxes m))) ms in
replace str matches;;
|
string.Templateを使ったバージョン。かなり冗長。orz ユニコード文字列と普通の文字列の両方に対応。
1 2 3 4 5 6 7 8 9 10 11 12 | # -*- coding: utf-8 -*-
import re, string
def include_tax(s):
strtype = type(s)
p = re.compile(r'([\d]+)')
s2 = re.sub(p, r'${_\1}', s)
s3 = string.Template(s2)
d = [(strtype('_%d' % n), int(n*1.05)) for n in map(int, re.findall(p, s))]
return s3.substitute(dict(d))
print include_tax(u'ダイコン150円、ハクサイ120円、ジャガイモ30円')
|
一応。Regexpライブラリって無いわけではないみたいだけど…
1 2 3 4 5 6 7 8 9 10 11 |





にしお
#3362()
Rating0/0=0.00
なお、税抜き価格は半角の数字の連なりで、かつ半角の数字の連なりはすべて税抜き価格だとします。「9,800円」「百円」「100円」「100g80円」などのような記述はないと考えてかまいません。 また税込み価格は税抜き価格の1.05倍で、端数は切り捨てとしてください。
[ reply ]