質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Scala

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

Q&A

解決済

4回答

371閲覧

文字列の操作について

colorful

総合スコア23

Scala

ScalaはJava仮想マシンで動作を行うオブジェクト指向型プログラミング言語の1つです。静的型付けの関数型言語で、コンパイルエラーの検出に強みがあります。

0グッド

0クリップ

投稿2019/02/05 03:22

編集2019/02/06 10:53

Aという関数にbとc(bとcはString型の変数)という引数を与えたら,bを返す処理を行いたいと考えています.
このようなプログラムを作成したいのですが,うまく解放が思い浮かばないので教えていただけないでしょうか.
≪定義≫
<関数>は、アルファベット大文字1字で表される。
<関数>は<引数>を2つ以上をとる。
記述例は以下の通りとする。
<関数><引数><引数>…

<引数>はアルファベット小文字1文字か、'('アルファベット小文字2文字以上')'である。
<引数>には同じまたは異なるアルファベット文字が与えられる。

以下は関数の動作例である。
Abc => b
A(bcd)(efg)=>(bcd)

仕様
関数Aは引数の2番目を捨てて引数を出現順にかえる。

(1)input => A<引数1><引数2>
output => <引数1>

(2)input => A<引数1><引数2><引数3>
output => <引数1><引数3>

(3)input => A(Abc)(def)
output => Abc =>bc

実現
処理は文字列の操作である。
先頭の1文字はアルファベット大文字1文字であればよいのでチェックしたら消す。
リストの2番目の要素を捨てる。
リスト全体を連結して1つの文字列にする。

現在の状況
今回は、<引数1>に入力された文字列が'('で始まった場合、それに対応する')'を削除するようにしたいと考えています。

そこで、今プログラムを考えているのですが

def unParentheses(len:String): String ={ var str = len.slice(0,len.length) var count = 0 var i = 0 for(i <- 0 to len.length){ if(len == '('){ count = count + 1 }else if(len == ')'){ count = count - 1 } } if(count == 0){ } return len }

count = 0のとき処理内容をどのように記載したらよいかが分からないのです。
アドバイスを頂けないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dice142

2019/02/05 04:42

bやcは変数名ですか?それとも"b", "c"という文字列ですか? 入力例や出力例があるとわかりやすいです。
退会済みユーザー

退会済みユーザー

2019/02/05 19:24

函数Aの引数はアルファベット1文字かブロック(xy)だと思いますが、混在は可能ですか? A(xy)bc Abc(xy)
colorful

2019/02/06 01:36

混在は可能です. A(xy)bcの例で言いますと まずA(xy)bの部分で処理を行い、(xy)を返し入力された文字列の中に残っているcと連結して、返却するようにしたいです。
papinianus

2019/02/06 08:12

(の場所を探しながらスライスするとかっていう制約があるなら、質問にはっきり書いていただけませんか?それが回答によって思いついたものででもです。また(xy)の文字数はどうも不定みたいですが、そういう点もです。質問の範囲内で回答したものが無駄になります。
colorful

2019/02/06 08:20

誤解を招くような文章で申し訳ありません。 皆さんの回答により、違った発想も思いついてしまいました。 「(の場所を探しながらスライスを行う」という制約があるわけではなく、スライスという機能を用いる他にも、for文で探してみる方法でも可能なのかなと思いました。 また、仰るように()の中の文字数は不定です。 言葉足らずのところがあり申し訳ありません。
papinianus

2019/02/06 08:24

謝って欲しいのではなく思っていることを追記してください。 forでみつけるのは、slice(など)に使うindexですよね?そうではない?もしかして、1文字ずつ出力(戻り値に足す)をしようとしている??
dice142

2019/02/06 08:29

本質問の目的は「解法を把握すること」ですよね? コードを書いて正しく実行できることと解法を把握することは別問題です。 このままだとコーディングして出てきた問題にまで突入しそうなので、 そのへんの区別をしていただければと。
colorful

2019/02/06 09:07

本質問でしたかったことは、コードを書いて正しく実行できることです。 <関数><引数1><引数2>があり、<引数1>にあたる引数が(xyz…)のように入力された場合、(から)までの中身のみを返すようにしたいということです。 誤解を招いてしまって、申し訳ないです。
colorful

2019/02/06 09:08

そのためには、for文を使ってまず()の処理を行うためにはどうしたらよいのか聞きたかっただけなのです。
dice142

2019/02/06 09:40

すみませんが、 > このようなプログラムを作成したいのですが,うまく解放が思い浮かばないので教えていただけないでしょうか. という文章から「解法を把握すること」が目的だと読み取ってしまいました。 解法が思いつかない状態からコードの完成は(作るものにもよりますが)あまりにも遠いです。 コーディングもそうですが、やりたいことを細分化し、わからないポイントに焦点を当てて質問することをおすすめします。 また、コーディングで質問があるのであればコードは提示しましょう。 質問のヒントにもありますが、あまりに質問の範囲が広かったり、コードの提示がない状態では 丸投げ質問だと認識されることがありますのでご注意ください。 https://teratail.com/help/question-tips#questionTips2
colorful

2019/02/06 09:57

すみません。 今、私は<関数><引数1><引数2>を与えたら<引数1>を返す処理を作っています。<引数1>に(が入力された場合は、それに対応する)を探し出し、()を除去したいと考えています。 今以下のプログラムを作成しているのですが、count = 0の時に(が入力された場合は、それに対応する)を探し出し、()の除去を行うようにするためには、どのように記述をしたら良いのか分からずに困っています。お助け願えないでしょうか? def unParentheses(len:String): String ={ var term = len.slice(0,len.length) var count = 0 var i = 0 for(i <- 0 to len.length){ if(len == '('){ count = count + 1 }else if(len == ')'){ count = count - 1 } } if(count == 0){ } return len }
dice142

2019/02/06 10:11

質問の要点は質問文を編集して修正してください。 コードもあるのでしたら載せてください。 一番気になるのは「()を除去したい」で元の質問と仕様が変わってしまっていることです。 詰まって困ったときは落ち着いて要点を確認してください。
dice142

2019/02/06 10:20

(ああ、コードあったのか。)と思ったらこれは質問文にあった仕様とは別物ですよね? これはどのタイミングで使おうとしている関数ですか? 質問の仕様から拡張されているものとしか思えないのですが。
colorful

2019/02/06 10:39

考えなおした結果、以上の質問に編集いたしました。 ごちゃごちゃしてしまって、申し訳ありません。
dice142

2019/02/06 10:48

コードはコードブロックで囲んでいただきたく。(「```」で囲むもしくはコードをドラッグして<code>ボタンを押す)
colorful

2019/02/06 10:53

失礼いたしました。 修正しました。
dice142

2019/02/06 11:00

追加でいろいろ聞きたいのですが、 ・本質問の目的というかゴールはどこですか? 「解法が思い浮かばない」のか「count=0のときの処理内容」なのか「コードが出来上がること」なのか。 先程書いたように範囲が広すぎると丸投げと解釈されかねないのでご注意を。 > 関数Aは引数の2番目を捨てて引数を出現順にかえる。 とありますが、出現順ってなんですか? > (3)input => A(Abc)(def) > output => Abc =>bc >仕様(3)のように関数に関数を適用した場合は、()を消去し、関数がなくなるまで処理を行う。 この仕様がよくわからないのですが、「A(Abc)(def)」→「Ab(def)」→「b」という流れではないですか? あるいは「A(Abc)(def)」→「(Abc)」→「b」かもしれませんが、どちらにせよ「bc」になる理由がわかりません。 > 今は()の数を数えて関数に関数を適用した場合にのみ()を消去し、それ以外というかアルファベット小文字の引数しか残ってない場合は()は残すようにしたい これを実現する関数を提示されていますが、これはどこからどのタイミングでどんな引数を受け取ってどんな値を返すのでしょうか。
colorful

2019/02/06 11:13

本質問の目的は、「count=0のときの処理内容」が分からないことです。 > 関数Aは引数の2番目を捨てて引数を出現順にかえる。 これは例えば、A<引数1><引数2>が与えられた場合<引数1>を返すと言いたかったです。 > (3)input => A(Abc)(def) > output => Abc =>bc >仕様(3)のように関数に関数を適用した場合は、()を消去し、関数がなくなるまで処理を行う。 すみません、これはこちらの計算ミスです。 計算過程の流れは「A(Abc)(def)」→「(Abc)」→「b」が正しいです。 今は()の数を数えて関数に関数を適用した場合にのみ()を消去し、それ以外というかアルファベット小文字の引数しか残ってない場合は()は残すようにしたい すみません、先ほどの編集でこの文を削除すること忘れてました。この文章は忘れてください。
dice142

2019/02/06 11:17

> 本質問の目的は、「count=0のときの処理内容」が分からないことです。 ということであれば、私の質問の最後の > これを実現する関数を提示されていますが、これはどこからどのタイミングでどんな引数を受け取ってどんな値を返すのでしょうか。 に対して答えていただけないと、そもそもその関数で何がしたいのか把握できないので、こちらで回答を修正できません。
colorful

2019/02/06 11:24

main関数の中でio.StdIn.readLine( )という機能を使って入力を行います。 そこで例えば、A(bc)(de)と入力されたら(bc)と出力されます。 つまり出力結果が’(’で始まる場合のみそれに対応する’)’の削除を行うようにこの関数のcount=0のときに行いたいです。
dice142

2019/02/06 11:28

いえ、なので、その削除を行うためにmain関数でunParenthesesという関数があるんですよね? このunParenthesesはどのタイミングで呼び出されてどんな引数を受け取って、どんな値を返すのですか?
colorful

2019/02/07 03:22

返信遅れて申し訳ありません。 unParenthesesという関数は、io.StdIn.readLine( )で入力された後とif(len.head=='A')の中で関数Aの処理を行った後の2回呼び出そうと考えています。 受け取る引数は、1回目の呼び出しの時は入力された文字列をそのまま受け取り、左端に(があった場合のみ対応する)を削除します。なければ、処理は行わずそのままmain関数に返します。 2回目は、Aという関数の初らが終わった後A<引数1><引数2>の<引数1>にあたる引数の左端に(があった場合のみ対応する)を削除します。なければ、処理は行わずそのままmain関数に返します。 このようなことを考えています。
dice142

2019/02/07 03:32

> 2回目は、Aという関数の初らが終わった後A<引数1><引数2>の<引数1>にあたる引数の左端に(があった場合のみ対応する)を削除します。なければ、処理は行わずそのままmain関数に返します。 Aという関数の処理が終わった場合は「A<引数1><引数2>」は「<引数1>」になっているので、 unParenthesesには「<引数1>」が渡されるという認識で間違いないですか?
colorful

2019/02/07 03:47

そのような認識で間違いないです。
dice142

2019/02/07 03:49

承知しました。ありがとうございます。
guest

回答4

0

何度か回答するうちに、質問者の質問パターンが見えてきました。
いつも例を示すことで仕様を提示していますが、例よりも言葉で仕様を定義する方が正確になります。
やってみます。間違っていたら訂正してください。

定義
<関数>とは、アルファベット大文字一字である。
<関数>は<引数>を2つ以上とる。関数の形式は次の通り。<関数><引数><引数> ...
<引数>は、アルファベット小文字1文字か、または、'('アルファベット小文字2文字')'である。
<引数>にはそれぞれ異なるアルファベット文字が与えられる。

以下は関数である。
Aab
Xabc
Y(xy)(zy)
Za(yz)bcd

以下は関数ではない。
B
Aa
C(z)

仕様
関数Aは引数の2番目を捨てて引数を出現順にかえす。

入力文字列:A<引数1><引数2>
出力文字列:<引数1>

入力文字列:A<引数1><引数2><引数3> ...
出力文字列:<引数1><引数3> ...

実現
処理は文字列の操作である。
先頭一文字はアルファベット大文字一字であれば良いので、チェックしたら捨てる。
引数の文字列をリストに変換する。
リストの二番目の要素を捨てる。
リスト全体を結合して一つの文字列にする。

以上

このような形式で質問して下されば、余計な質疑応答がなくなります。
実現のところに具体的なソースコードやエラーメッセージが書けるようになるとなお良いです。

ヒント

slice()を使わず、正規表現を使うことをすすめます。

ヒント:引数を取り出してListに格納する。

Scala

1"(\([a-z]{2}\)|[a-z])".r.findAllIn("Abcd").toList 2"(\([a-z]{2}\)|[a-z])".r.findAllIn("A(xy)(yz)(za)").toList

ヒント:listの2番目の要素を削除する。リストに格納する型は無関係です。

Scala

1def drop2nd[T](list:List[T]):List[T] = if (list.isEmpty) list else list.head :: list.drop(2)

ヒントをもとに考えてみましょう。必要なら新しい質問をしてください。

別解 scala-paser-combinators 紹介 (2019-02-07)

パーサーコンビネーター
Scalaのパーサーコンビネーターを使って問題を解いてみました。
『Scala スケーラブルプログラミング 第3版』インプレス - 第33章 パーサー・コンビネーター

質問の関数をEBNFで記述しました。

EBNF

1function ::= functionHeader argList 2argList ::= argLiteral args 3args ::= argLiteral [args] 4functionHeader ::= (A| .. |Z) 5argLiteral ::= ((smallAlpha smallAlpha)| smallAlpha ) 6smallAlpha ::= (a| .. |z)

記述したEBNFをもとに、scala.util.parsing.combinator.RegexParsersを使って、パーサーを作成します。^^に続けてパース後に実行する動作を記述します。動作は関数の第二引数を削除して、それ以外の引数を表示する処理になります。

Scala

1import scala.util.parsing.combinator._ 2class FunctionParserEval extends RegexParsers { 3 4 def expr: Parser[String] = function ^^ {_.mkString} 5 def function: Parser[List[String]] = functionHeader~argList ^^ { case _ ~ b => b.head :: b.drop(2) } 6 def argList: Parser[List[String]] = argLiteral~args ^^ { case a ~ b => a::b } 7 def args: Parser[List[String]] = argLiteral~opt( args ) ^^ { 8 case a ~ None => a :: Nil 9 case a ~ Some(b) => a :: b 10 } 11 def argLiteral: Parser[String] = "(\([a-z]{2}\)|[a-z])".r 12 def functionHeader: Parser[String] = "[A-Z]".r 13 14 def parse(str:String) = parseAll(expr,str) 15}

パーサーに関数文字列を入力して評価し、結果を表示します。第二引数を削除した引数が表示されます。

Scala

1val parserEval = new FunctionParserEval 2println(parserEval.parse("Aabcd")) 3println(parserEval.parse("A(xy)(yz)(za)"))

build.sbt
パーサーコンビネーターは、最新のScala基本パッケージに同梱されていないので、sbt環境にダウンロードします。

sbt

1"org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.1"

参考
https://github.com/scala/scala-parser-combinators

投稿2019/02/05 20:28

編集2019/02/07 09:19
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

colorful

2019/02/06 01:36 編集

回答していただき、ありがとうございます。 仕様は、記述していただいた通りです。 エラーメッセージ自体は出ていないのですが、<関数>(文字列)(文字列)が入力された場合の( )の区切り方の処理が分からないのです。 書いたプログラムは、 len:String var x = "" var y = "" if(len.length != 1){ x = len.drop(1) }else if(x.head =='(' && x.last ==')' && y.head=='('&&y.last == ')'){ term = A(x,y) return term } です。 考えていることは、slice()の機能を使って、あらかじめnullで定義した変数に代入して(例:var x,x=len.slice(0,len.length)という感じ)if文で処理を行いたいなと考えています。
colorful

2019/02/06 01:33

ただ、slice()を使う場合、どこからどこまでを指定して良いのかが分からなくて困ってます。 そこで、解決策の方法があれば教えていただけないでしょうか。
退会済みユーザー

退会済みユーザー

2019/02/06 03:29

slice()を使うとすれば、開始インデックスと、終了インデックスが必要です。現在のインデックスも必要になるでしょう。C言語の例を探すと望むコードが見つかるかもしれません。 他の人の回答にあるように、正規表現を使う使うことを薦めます。正規表現は習得に時間がかかるかもしれませんが、知っておけば役に立つでしょう。必要なら正規表現の質問をしてください。 長くなるので、回答にヒントを書いておきます。
colorful

2019/02/06 07:39

回答ありがとうございます。 括弧の処理についてなのですが、別の関数を作成しiとcountという変数を作成し、for(i<-0 to len.length){ if( len =='('){ count = count + 1}else if(len ==')'){ count = count - 1} return 0}としての処理でもできたりしますか?
退会済みユーザー

退会済みユーザー

2019/02/06 09:34

15分程度で書いたコードです。参考にしてください。 def extractArgs(s:String):List[String] = { var wl:List[String] = List() var spos=0;var epos=0;var pos=0 val maxL = s.length while(pos>=0 && pos<maxL){ spos=s.indexOf("(",pos) println(s"0 spos ${spos}, epos ${epos}") if (spos >= 0) { epos=s.indexOf(")",spos) println(s"1 spos ${spos}, epos ${epos}") if (epos > spos) { pos=epos+1 println(s"2 spos ${spos}, epos ${epos} "+s.slice(spos,pos)) wl = s.slice(spos,pos) :: wl } else {pos = -1} } else {pos = -1} } wl } 使い方は、extractArgs("(ab)(cd)(ef)")
colorful

2019/02/06 11:01

ありがとうございます。  参考にします。
guest

0

現在の状況

今回は、<引数1>に入力された文字列が'('で始まった場合、それに対応する')'を削除するようにしたいと考えています。

この現在の問題、解決したい目的に対して「文字列で'('や')'でカウンタを増減させる」はあまりにも無力です。

Scala

1 val str = io.StdIn.readLine() 2 val result = trimParen(str) 3 println(result) 4 5 def trimParen(s : String) : String = { 6 val length = s.length //文字の長さ 7 val firstChar = s(0) //最初の文字 8 val lastChar = s(length -1) //最後の文字(0から数えはじめるので-1) 9 if(firstChar == '(') { //最初の文字は(であって 10 if(lastChar == ')') { //さらに最後が)であるなら 11 return s.slice(1,s.length - 1) //1文字目から最後の文字の手前までを返す 12 } 13 } 14 s //さもなくば元の文字を返す 15 }

このコードがScala的であるとは全く思わないのですが、カウントでは求まらない。そこだけは申し訳ないが諦めてください。

参考までに

Scala

1 //def unParentheses(len:String): Boolean ={ 2 def is括弧の個数が対応しているか(len:String): Boolean ={ 3 //var str = len.slice(0,len.length) 4 var count = 0 5 var i = 0 6 7 for(i <- 0 to len.length-1){ //-1まで 8 if(len(i) == '('){ //lenではなくlen(i) 9 count = count + 1 10 } else if(len(i) == ')'){ 11 count = count - 1 12 } 13 } 14 if(count == 0){ //(があると+1、)があると-1して求まった0は(と)の個数が同じということ 15 return true; 16 } 17 false 18 }

さらに参考。最初のクイズをforでといてみた。これで分からなかったらもう私には説明する能力がない

Scala

1 val str = io.StdIn.readLine() //"A(xyw)(stU)cdefg"などと手で入力する 2 val result = imperative(str) 3 println(result) 4 5 def imperative(str:String): String ={ 6 var ret = "" //最後にリターンするまで組みあげていく文字列 7 var block = 1 // <A><引数1><引数2><引数3>の概念的なブロック、最初のAはブロック1 8 var canOutput = false //ブロックがスキップされるものであるか、出力されるものであるかのフラグ、最初の1文字を出さないのでfalse 9 var isInsideKakko = false //カッコ継続中かどうかのフラグ、最初はカッコ外 10 11 for(i <- 0 to str.length - 1) { //文字列のはしからはしまで 12 //出力フェイズ 13 if(canOutput || block > 3) { //出力可能であるかをフラグもしくは第3ブロック以降かで判定 14 if(str(i) != '(' && str(i) != ')') { //()を出力したくないようなので、()でないときだけ 15 ret += str(i) //出力文字列に、現在の文字を書く 16 } 17 } 18 19 //状態管理フェイズ 20 if(str(i) == '(') { //(が来たら、カッコ継続中フラグをオンにする 21 isInsideKakko = true 22 } else { //(以外の文字であるとき 23 if(str(i) == ')') { //)であればもはやカッコ継続フラグをオフにする 24 isInsideKakko = false 25 } 26 if(!isInsideKakko) { //カッコがないと考える(Abc)と、1文字ずつがブロックであり、かつ1文字ずつ非出力、出力、非出力とかわっていく。 27 //カッコが終わったときも、ブロックがかわり、出力・非出力が切り変わる。 28 canOutput = !canOutput 29 block += 1 30 } //出力状態・非出力状態はカッコ継続中はかわらないが、かわらないということはプログラムでやることがないのでelseはなし 31 } 32 } 33 ret //作ったものを返す 34 }

このクイズ出したり、質問者様にScalaを教えたりしてる人にも問題ある気がする

現時点の質問に追記されたコードは、書かれていないコーダーの気持ちを斟酌するに、カッコの対応が取れているかをもっぱら個数の側面から見ようとするものだと読み取りました。

従ってcountが0のときにはtrueをreturnするのが妥当だと考えます。なおelseである、0以外のときにはfalseを返すべきと思料します。

投稿2019/02/06 13:04

編集2019/02/06 16:52
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

colorful

2019/02/07 03:15

回答していただき、ありがとうございます。 書いて下さったプログラム、分かりやすいです。 参考にさせていただきます。
papinianus

2019/02/07 08:19

> 書いて下さったプログラム、分かりやすいです 私にとって何よりうれしいお言葉です。しかし一方でこれはcolorful様が小難しいプログラムなるものについて悩んだからこそ生まれたコードです。どの質問もそうですが、質問者様が困っていることを具体的にすればするほどご本人に望ましい回答が得られるはずです。
colorful

2019/02/08 05:29

今回、教えていただきありがとうございます。 質問をさせていただくときも、具体化出来るように改善していきたいと思います。 今後ともよろしくお願いします。
guest

0

ベストアンサー

質問の意図がだいぶわからなかったんですが、他の回答とか質問履歴からして、文字列の字句解析をしたいってことですよね?

unParenthesesは前の質問のをパクって来ました。
でも、()は残していいのね。まあ取るほうが容易だと思うんで入れたままにしときます。

質問例の要件からすると、正規表現でパースしたらいいのかなーと思ったんでパーサを書きました
caseの冒頭で、どの例示パターンかも書いてます

Scala

1 println(parser(io.StdIn.readLine())) //これがキーボードからの入力を処理して、表示として返すコードです 2 3 //以下、本回答が仕様に添った動作をするかを簡便に確認できるように良かれと思って出力(println)コードを書きました。 4 println(parser("Abc")) 5 println(parser("Abcd")) 6 println(parser("A(xy)(yz)")) 7 println(parser("A(ab)(cd)(ef)")) 8 def unParentheses(s:String):String = if (!s.isEmpty && s.head == '(' && s.last == ')') unParentheses(s.drop(1).dropRight(1)) else s 9 def parser(in:String):String = { 10 val pattern = """^A([^(]|(.{2}))([^(]|(.{2}))(.+|$)""".r 11 in match { 12 case pattern(b,c,"") => s"1,2 ${unParentheses(b)}" 13 case pattern(b,c,d) => s"3 ${unParentheses(b)}${unParentheses(d)}" 14 case _ => "None" 15 } 16 }

投稿2019/02/06 02:33

編集2019/02/06 08:04
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

colorful

2019/02/06 07:45

ご回答ありがとうございます。 文字列は、printlnで表示した文字列の括弧を処理するのではなく、キーボードから入力した文字列を処理することを想定しています。 正規表現のやり方を教えていただきありがとうございました。
papinianus

2019/02/06 08:02

> 文字列は、printlnで表示した文字列の括弧を処理するのではなく、キーボードから入力した文字列を処理することを想定しています。 失礼ながら関数の呼びかたを理解しておられますか?そのようなことは全くしていません。 > キーボードから入力した文字列を処理 する部分まで明示しないと回答として認めてもらえないなんて思いませんでした。 追記します。
colorful

2019/02/06 08:26

返信ありがとうございます。 関数の呼び方は、一応理解しております。 あと申し訳ありません。 printlnを用いていらしたので、私の質問文で誤解をあたえてしまったのかなと思いました。
colorful

2019/02/06 08:26

返信ありがとうございます。 関数の呼び方は、一応理解しております。 あと申し訳ありません。 printlnを用いていらしたので、私の質問文で誤解をあたえてしまったのかなと思いました。
papinianus

2019/02/07 08:23

ポエムです。無視推奨 このdeus ex machinaな回答はまさに神様のバチ的なある種の暴力性があると思います。方向性が明示されなければそれは避けがたい。誰もがよりよい答えをしようと思っているでしょうが、理解しやすいものが常によい訳ではないですから。 ただ、私は、こうした機械仕掛けの神をまねぶあるいは読み解くことで、得られるものもあると思って回答しております。
guest

0

入出力例からなんとなくやりたそうなことはわかったので、
提示されたやりたいことを整理してみました。

メインの流れ

  1. 入力された文字列を読み込む
  2. 関数呼び出し&結果受け取り
  3. 結果表示

関数内の流れ

  • 引数として文字列(strとする)を受け取る
  1. strを「A」「ブロック1」「ブロック2」「残り」で分ける

※ブロックとは「(xy)」のように囲まれた文字列or「b」のような1文字を想定

  1. 「ブロック1」と「残り」を連結し、その連結した値を返す

b, cは変数と仰っているので、もしかしたら文字列を切り分ける処理はメインで行うかもしれません。
やりたいことを処理順に書き直し、少しずつプログラムに起こしてみてください。


ブロックの抽出方法について

sliceを使って行うとのことなので、A(bc)(de)のような単純な場合の考え方を書いておきます。

  1. ブロック1の開始(2文字目)が(かどうか調べます

(であれば)の位置をindexOfで取得し、(...)の文字列をsliceで取得します
(でなければそのまま2文字目だけを取得します

  1. ブロック1の最後の文字()or2文字目)の次の文字が(か調べます

(であれば)の位置をindexOfで取得し、(...)の文字列をsliceで取得します
(でなければその部分の文字だけを取得します

一例ですが、こんな感じで取れるかと思います。


unParentheses関数について

この関数内でやりたいことが

  • 受け取った文字列が(で始まっていれば、対応する)を探し、その()を削除して返す
  • 受け取った文字列が(で始まっていなければ、受け取った文字列をそのまま返す

とのことなので、対応する)を探すのに必要な手順を書いておきます。

  1. 受け取った文字列の0文字目から順に調べる
  2. i文字目が(であればカウンタを+1、)であればカウンタを-1する
  3. カウンタが0になった地点の)(に対応する)であるので、その位置を記録してループを抜ける。
  4. 0文字目を削除する(1文字目以降を詰める)
  5. 記録した)の位置を削除する(それより後ろを詰める)
  6. ()を削除した文字列を返す

()を削除する処理はsliceを使ったほうが楽です。
また、受け取る文字列に制約があれば(括弧の入れ子がないとか)もっとシンプルな方法があるはずです。
(制約によりますが。)

投稿2019/02/05 10:44

編集2019/02/07 04:52
dice142

総合スコア5158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

colorful

2019/02/05 11:58

回答していただき、ありがとうございます。 紙に処理をどのようにやっていくか整理してやってみたところ、(実行結果_例1)と(実行結果_例3)は無事解決いたしました。 しかし色々考えてみた結果、(実行結果_例2)と(実行結果_例4)のブロック1とブロック2にあたる処理をどのようにやったらよいかの解決に至らなかったので、教えていただけないでしょうか。
dice142

2019/02/06 01:33

シンプルなパターンであれば「(」があれば「)」まで取得のような処理をする必要があります。 あるいは正規表現を使ってもいいですね。
colorful

2019/02/06 01:40 編集

Slice()を用いて考えているのですが、Slice()の()の中に指定する範囲は、どのようにしたら良いのかで詰まっています。 ここは、正規表現の方がよいのでしょうか?
dice142

2019/02/06 02:07

何文字目から何文字目という範囲が分かるのであればSliceでもできます。 正規表現じゃないとダメということはないです。
colorful

2019/02/06 02:29

()の中の文字数は決まっていないので、Scalaの何の機能を使って(str.sliceやstr.IndexOfなど)良いのかが分からなくて困っております。
dice142

2019/02/06 02:39

sliceを使うのならindexOfで「(」と「)」の位置を取得すれば良いでしょう。 で、sliceで「(」の位置から「)」の位置までを取り出せば良いです。 indexOfは開始位置を指定できるので、2ブロック目の位置を探すには 1ブロック目の最後の次の文字からを指定すれば探せるはずです。
dice142

2019/02/06 02:40

「A(b(c))d」みたいな入れ子になっているイレギュラーは一旦考えてないです。
dice142

2019/02/06 02:58

ブロックの取り出し方を回答に追記しました。
colorful

2019/02/06 07:42

回答ありがとうございます。 sliceなどを使わずにcountという変数とfor文用いて、括弧の数を数えて処理する関数を呼び出して使う方法もありですか?
dice142

2019/02/06 08:12

方法は一つではないので、実現可能であるならありだと思います。 ただし、それが最善の方法かどうかは別問題なので、 あくまでも「動くこと」が目的であるなら「あり」だと私は思います。
colorful

2019/02/06 08:22

ありがとうございます。 とりあえず、最低限「動くこと」を目的としています。 回答していただいたことを参考に1度考えてみたいと思います。
dice142

2019/02/07 04:52

unParentheses関数について回答に追記しました。
colorful

2019/02/07 07:16

追記していただきありがとうございます。 是非参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問